mirror of
https://github.com/apache/struts.git
synced 2026-08-11 01:27:14 +00:00
WW-4198 Merges changes to develop
This commit is contained in:
@@ -120,7 +120,7 @@ END SNIPPET: supported-validators
|
||||
<#if validator.shortCircuit>continueValidation = false;</#if>
|
||||
}
|
||||
<#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;</#if>
|
||||
|
||||
@@ -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);
|
||||
|
||||
+6
@@ -528,6 +528,12 @@ public class AnnotationValidationConfigurationBuilder {
|
||||
} 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)
|
||||
|
||||
+10
-66
@@ -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;
|
||||
@@ -22,75 +21,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: description -->
|
||||
* This validator checks that a field is a valid URL.
|
||||
* <!-- END SNIPPET: description -->
|
||||
*
|
||||
* <p/> <u>Annotation usage:</u>
|
||||
*
|
||||
* <!-- START SNIPPET: usage -->
|
||||
* <p/>The annotation must be applied at method level.
|
||||
* <!-- END SNIPPET: usage -->
|
||||
*
|
||||
* <p/> <u>Annotation parameters:</u>
|
||||
*
|
||||
* <!-- START SNIPPET: parameters -->
|
||||
* <table class='confluenceTable'>
|
||||
* <tr>
|
||||
* <th class='confluenceTh'> Parameter </th>
|
||||
* <th class='confluenceTh'> Required </th>
|
||||
* <th class='confluenceTh'> Default </th>
|
||||
* <th class='confluenceTh'> Notes </th>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td class='confluenceTd'>message</td>
|
||||
* <td class='confluenceTd'>yes</td>
|
||||
* <td class='confluenceTd'> </td>
|
||||
* <td class='confluenceTd'>field error message</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td class='confluenceTd'>key</td>
|
||||
* <td class='confluenceTd'>no</td>
|
||||
* <td class='confluenceTd'> </td>
|
||||
* <td class='confluenceTd'>i18n key from language specific properties file.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td class='confluenceTd'>messageParams</td>
|
||||
* <td class='confluenceTd'>no</td>
|
||||
* <td class='confluenceTd'> </td>
|
||||
* <td class='confluenceTd'>Additional params to be used to customize message - will be evaluated against the Value Stack</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td class='confluenceTd'>fieldName</td>
|
||||
* <td class='confluenceTd'>no</td>
|
||||
* <td class='confluenceTd'> </td>
|
||||
* <td class='confluenceTd'> </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td class='confluenceTd'>shortCircuit</td>
|
||||
* <td class='confluenceTd'>no</td>
|
||||
* <td class='confluenceTd'>false</td>
|
||||
* <td class='confluenceTd'>If this validator should be used as shortCircuit.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td class='confluenceTd'>type</td>
|
||||
* <td class='confluenceTd'>yes</td>
|
||||
* <td class='confluenceTd'>ValidatorType.FIELD</td>
|
||||
* <td class='confluenceTd'>Enum value from ValidatorType. Either FIELD or SIMPLE can be used here.</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* <!-- END SNIPPET: parameters -->
|
||||
*
|
||||
* <p/> <u>Example code:</u>
|
||||
*
|
||||
* <pre>
|
||||
* <!-- START SNIPPET: example -->
|
||||
* @UrlValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
|
||||
* <!-- END SNIPPET: example -->
|
||||
* </pre>
|
||||
*
|
||||
* @author Rainer Hermanns
|
||||
* @version $Id$
|
||||
*/
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@@ -121,7 +56,6 @@ public @interface UrlValidator {
|
||||
* If this is activated, the validator will be used as short-circuit.
|
||||
*
|
||||
* Adds the short-circuit="true" attribute value if <tt>true</tt>.
|
||||
*
|
||||
*/
|
||||
boolean shortCircuit() default false;
|
||||
|
||||
@@ -130,4 +64,14 @@ public @interface UrlValidator {
|
||||
*/
|
||||
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 "";
|
||||
|
||||
}
|
||||
|
||||
+44
-22
@@ -17,28 +17,12 @@ package com.opensymphony.xwork2.validator.validators;
|
||||
|
||||
import com.opensymphony.xwork2.validator.ValidationException;
|
||||
import com.opensymphony.xwork2.util.URLUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
*
|
||||
* URLValidator checks that a given field is a String and a valid URL
|
||||
*
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*
|
||||
* <p/>
|
||||
*
|
||||
* <!-- START SNIPPET: parameters -->
|
||||
*
|
||||
* <ul>
|
||||
* <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li>
|
||||
* </ul>
|
||||
*
|
||||
* <!-- END SNIPPET: parameters -->
|
||||
*
|
||||
* <p/>
|
||||
*
|
||||
* <pre>
|
||||
* <!-- START SNIPPET: examples -->
|
||||
* <validators>
|
||||
* <!-- Plain Validator Syntax -->
|
||||
* <validator type="url">
|
||||
@@ -53,15 +37,13 @@ import com.opensymphony.xwork2.util.URLUtil;
|
||||
* </field-validator>
|
||||
* </field>
|
||||
* </validators>
|
||||
* <!-- END SNIPPET: examples -->
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author $Author$
|
||||
* @version $Date$ $Revision$
|
||||
*/
|
||||
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 +54,48 @@ public class URLValidator extends FieldValidatorSupport {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,9 +17,12 @@ package com.opensymphony.xwork2.validator;
|
||||
|
||||
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 class URLValidatorTest extends XWorkTestCase {
|
||||
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 class URLValidatorTest extends XWorkTestCase {
|
||||
return "http://yahoo.com/articles?id=123";
|
||||
}
|
||||
}
|
||||
|
||||
class MyAction {
|
||||
|
||||
public String getUrlRegex() {
|
||||
return "myapp:\\/\\/[a-z]*\\.com";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user