From 31be88afa28fb9b1e9854d0d7673ab9b979cf9be Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 9 Mar 2014 21:01:15 +0100 Subject: [PATCH 1/5] Extends validator to allow set predefined regex used to validate URLs --- .../validator/validators/URLValidator.java | 46 +++++++++++++++++ .../xwork2/validator/URLValidatorTest.java | 50 +++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java b/xwork-core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java index b4a1287955..4f63961251 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java @@ -17,6 +17,7 @@ import com.opensymphony.xwork2.validator.ValidationException; import com.opensymphony.xwork2.util.URLUtil; +import org.apache.commons.lang3.StringUtils; /** * @@ -31,6 +32,8 @@ * * * * @@ -62,6 +65,9 @@ */ public class URLValidator extends FieldValidatorSupport { + private String urlRegex; + private String urlRegexExpression; + public void validate(Object object) throws ValidationException { String fieldName = getFieldName(); Object value = this.getFieldValue(fieldName, object); @@ -72,8 +78,48 @@ public void validate(Object object) throws ValidationException { return; } + // FIXME deprecated! the same regex below should be used instead + // replace logic with next major release if (!(value.getClass().equals(String.class)) || !URLUtil.verifyUrl((String) value)) { addFieldError(fieldName, object); } } + + /** + * This is used to support client-side validation, it's based on + * http://stackoverflow.com/questions/161738/what-is-the-best-regular-expression-to-check-if-a-string-is-a-valid-url + * + * @return regex to validate URLs + */ + public String getUrlRegex() { + if (StringUtils.isNotEmpty(urlRegexExpression)) { + return (String) parse(urlRegexExpression, String.class); + } else if (StringUtils.isNotEmpty(urlRegex)) { + return urlRegex; + } else { + return "^(https?|ftp):\\/\\/" + + "(([a-z0-9$_\\.\\+!\\*\\'\\(\\),;\\?&=-]|%[0-9a-f]{2})+" + + "(:([a-z0-9$_\\.\\+!\\*\\'\\(\\),;\\?&=-]|%[0-9a-f]{2})+)?" + + "@)?(#?" + + ")((([a-z0-9]\\.|[a-z0-9][a-z0-9-]*[a-z0-9]\\.)*" + + "[a-z][a-z0-9-]*[a-z0-9]" + + "|((\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])\\.){3}" + + "(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])" + + ")(:\\d+)?" + + ")(((\\/+([a-z0-9$_\\.\\+!\\*\\'\\(\\),;:@&=-]|%[0-9a-f]{2})*)*" + + "(\\?([a-z0-9$_\\.\\+!\\*\\'\\(\\),;:@&=-]|%[0-9a-f]{2})*)" + + "?)?)?" + + "(#([a-z0-9$_\\.\\+!\\*\\'\\(\\),;:@&=-]|%[0-9a-f]{2})*)?" + + "$"; + } + } + + public void setUrlRegex(String urlRegex) { + this.urlRegex = urlRegex; + } + + public void setUrlRegexExpression(String urlRegexExpression) { + this.urlRegexExpression = urlRegexExpression; + } + } diff --git a/xwork-core/src/test/java/com/opensymphony/xwork2/validator/URLValidatorTest.java b/xwork-core/src/test/java/com/opensymphony/xwork2/validator/URLValidatorTest.java index 97248952e6..f495557347 100644 --- a/xwork-core/src/test/java/com/opensymphony/xwork2/validator/URLValidatorTest.java +++ b/xwork-core/src/test/java/com/opensymphony/xwork2/validator/URLValidatorTest.java @@ -17,9 +17,12 @@ import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.XWorkTestCase; +import com.opensymphony.xwork2.util.URLUtil; import com.opensymphony.xwork2.util.ValueStack; import com.opensymphony.xwork2.validator.validators.URLValidator; +import java.util.regex.Pattern; + /** * Test case for URLValidator * @@ -103,6 +106,46 @@ public void testValidUrl2() throws Exception { assertFalse(validator.getValidatorContext().hasFieldErrors()); } + public void testValidUrlWithRegex() throws Exception { + URLValidator validator = new URLValidator(); + + validator.setUrlRegex("^myapp:\\/\\/[a-z]*\\.com$"); + + Pattern pattern = Pattern.compile(validator.getUrlRegex()); + + assertTrue(pattern.matcher("myapp://test.com").matches()); + assertFalse(pattern.matcher("myap://test.com").matches()); + } + + public void testValidUrlWithRegexExpression() throws Exception { + URLValidator validator = new URLValidator(); + ActionContext.getContext().getValueStack().push(new MyAction()); + validator.setValueStack(ActionContext.getContext().getValueStack()); + validator.setUrlRegexExpression("${urlRegex}"); + + Pattern pattern = Pattern.compile(validator.getUrlRegex()); + + assertTrue(pattern.matcher("myapp://test.com").matches()); + assertFalse(pattern.matcher("myap://test.com").matches()); + } + + public void testValidUrlWithDefaultRegex() throws Exception { + URLValidator validator = new URLValidator(); + + Pattern pattern = Pattern.compile(validator.getUrlRegex()); + + assertFalse(pattern.matcher("myapp://test.com").matches()); + assertFalse(pattern.matcher("myap://test.com").matches()); + assertFalse(pattern.matcher("").matches()); + assertFalse(pattern.matcher(" ").matches()); + assertFalse(pattern.matcher("no url").matches()); + + assertTrue(pattern.matcher("http://www.opensymphony.com").matches()); + assertTrue(pattern.matcher("https://www.opensymphony.com").matches()); + assertTrue(pattern.matcher("https://www.opensymphony.com:443/login").matches()); + assertTrue(pattern.matcher("http://localhost:8080/myapp").matches()); + } + @Override protected void setUp() throws Exception { super.setUp(); @@ -140,4 +183,11 @@ public String getTestingUrl5() { return "http://yahoo.com/articles?id=123"; } } + + class MyAction { + + public String getUrlRegex() { + return "myapp:\\/\\/[a-z]*\\.com"; + } + } } From 3457a656ba95539145ef3b19d254fe0129b4d187 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 9 Mar 2014 21:01:44 +0100 Subject: [PATCH 2/5] Marks method as deprecated --- .../src/main/java/com/opensymphony/xwork2/util/URLUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/util/URLUtil.java b/xwork-core/src/main/java/com/opensymphony/xwork2/util/URLUtil.java index b9aaee7cf2..160a5b99bb 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/util/URLUtil.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/util/URLUtil.java @@ -33,6 +33,7 @@ public class URLUtil { * @param url The url string to verify. * @return a boolean indicating whether the URL seems to be incorrect. */ + @Deprecated public static boolean verifyUrl(String url) { if (LOG.isDebugEnabled()) { LOG.debug("Checking if url [#0] is valid", url); From 3f6ce657da3ac6c133939bfcebb4e4e5f6bd2bc1 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 9 Mar 2014 21:02:27 +0100 Subject: [PATCH 3/5] Adds usage of new urlRegex field in client side validation --- core/src/main/resources/template/xhtml/form-close-validate.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/template/xhtml/form-close-validate.ftl b/core/src/main/resources/template/xhtml/form-close-validate.ftl index 81a17e1e19..f129156e50 100644 --- a/core/src/main/resources/template/xhtml/form-close-validate.ftl +++ b/core/src/main/resources/template/xhtml/form-close-validate.ftl @@ -120,7 +120,7 @@ END SNIPPET: supported-validators <#if validator.shortCircuit>continueValidation = false; } <#elseif validator.validatorType = "url"> - if (continueValidation && fieldValue != null && fieldValue.length > 0 && fieldValue.match("${validator.regex?js_string}")==null) { + if (continueValidation && fieldValue != null && fieldValue.length > 0 && fieldValue.match("/${validator.urlRegex?js_string}/i")==null) { addError(field, error); errors = true; <#if validator.shortCircuit>continueValidation = false; From e66a3062992fac588cf3f570a224bbe7d9ce5ef5 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 9 Mar 2014 21:04:11 +0100 Subject: [PATCH 4/5] Extends annotation to support new URL regex parameters --- ...otationValidationConfigurationBuilder.java | 6 ++ .../validator/annotations/UrlValidator.java | 74 +++---------------- 2 files changed, 16 insertions(+), 64 deletions(-) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilder.java b/xwork-core/src/main/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilder.java index 6ab06a94c8..dbd8975246 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilder.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilder.java @@ -528,6 +528,12 @@ private ValidatorConfig processUrlValidatorAnnotation(UrlValidator v, String fie } else if (v.fieldName() != null && v.fieldName().length() > 0) { params.put("fieldName", v.fieldName()); } + if (StringUtils.isNotEmpty(v.urlRegex())) { + params.put("urlRegex", v.urlRegex()); + } + if (StringUtils.isNotEmpty(v.urlRegexExpression())) { + params.put("urlRegexExpression", v.urlRegexExpression()); + } validatorFactory.lookupRegisteredValidatorType(validatorType); return new ValidatorConfig.Builder(validatorType) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java b/xwork-core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java index fb6fa3c865..a06db12593 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java @@ -22,75 +22,12 @@ import java.lang.annotation.Target; /** - * * This validator checks that a field is a valid URL. - * - * - *

Annotation usage: - * - * - *

The annotation must be applied at method level. - * - * - *

Annotation parameters: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Parameter Required Default Notes
messageyes field error message
keyno i18n key from language specific properties file.
messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
fieldNameno  
shortCircuitnofalseIf this validator should be used as shortCircuit.
typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
- * - * - *

Example code: * *

- * 
  * @UrlValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
- * 
  * 
* - * @author Rainer Hermanns - * @version $Id$ */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @@ -121,7 +58,6 @@ * If this is activated, the validator will be used as short-circuit. * * Adds the short-circuit="true" attribute value if true. - * */ boolean shortCircuit() default false; @@ -130,4 +66,14 @@ */ ValidatorType type() default ValidatorType.FIELD; + /** + * Defines regex to use to validate url + */ + String urlRegex() default ""; + + /** + * Defines regex as an expression which will be evaluated to string and used to validate url + */ + String urlRegexExpression() default ""; + } From e585490656225f88dc28300b722ec38dcffbb6ba Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 9 Mar 2014 21:22:28 +0100 Subject: [PATCH 5/5] Moves snippets to wiki --- .../validator/annotations/UrlValidator.java | 2 -- .../validator/validators/URLValidator.java | 24 ------------------- 2 files changed, 26 deletions(-) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java b/xwork-core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java index a06db12593..9ad922311e 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.opensymphony.xwork2.validator.annotations; import java.lang.annotation.ElementType; @@ -27,7 +26,6 @@ *
  * @UrlValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
  * 
- * */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java b/xwork-core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java index 4f63961251..767416debf 100644 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java +++ b/xwork-core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java @@ -20,28 +20,9 @@ import org.apache.commons.lang3.StringUtils; /** - * - * * URLValidator checks that a given field is a String and a valid URL - * - * - * - *

- * - * - * - *

    - *
  • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
  • - *
  • urlRegexExpression - The regex defined as expression used to validate url. If not defined 'urlRegex' will be used instead
  • - *
  • urlRegex - The regex used to validate url. If not defined default regex will be used
  • - *
- * - * - * - *

* *

- * 
  * <validators>
  *      <!-- Plain Validator Syntax -->
  *      <validator type="url">
@@ -56,12 +37,7 @@
  *          </field-validator>
  *      </field>
  * </validators>
- * 
  * 
- * - * - * @author $Author$ - * @version $Date$ $Revision$ */ public class URLValidator extends FieldValidatorSupport {