2
* Copyright 2005-2012 Restlet S.A.S.
4
* The contents of this file are subject to the terms of one of the following
5
* open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
6
* 1.0 (the "Licenses"). You can select the license that you prefer but you may
7
* not use this file except in compliance with one of these Licenses.
9
* You can obtain a copy of the Apache 2.0 license at
10
* http://www.opensource.org/licenses/apache-2.0
12
* You can obtain a copy of the LGPL 3.0 license at
13
* http://www.opensource.org/licenses/lgpl-3.0
15
* You can obtain a copy of the LGPL 2.1 license at
16
* http://www.opensource.org/licenses/lgpl-2.1
18
* You can obtain a copy of the CDDL 1.0 license at
19
* http://www.opensource.org/licenses/cddl1
21
* You can obtain a copy of the EPL 1.0 license at
22
* http://www.opensource.org/licenses/eclipse-1.0
24
* See the Licenses for the specific language governing permissions and
25
* limitations under the Licenses.
27
* Alternatively, you can obtain a royalty free commercial license with less
28
* limitations, transferable or non-transferable, directly at
29
* http://www.restlet.com/products/restlet-framework
31
* Restlet is a registered trademark of Restlet S.A.S.
34
package org.restlet.routing;
36
import java.util.List;
37
import java.util.concurrent.CopyOnWriteArrayList;
38
import java.util.regex.Pattern;
40
import org.restlet.Context;
41
import org.restlet.Request;
42
import org.restlet.Response;
43
import org.restlet.Restlet;
44
import org.restlet.data.Status;
47
* Filter validating attributes from a call. Validation is verified based on
48
* regex pattern matching.<br>
50
* Concurrency note: instances of this class or its subclasses can be invoked by
51
* several threads at the same time and therefore must be thread-safe. You
52
* should be especially careful when storing state in member variables.
54
* @author Jerome Louvel
57
public class Validator extends Filter {
58
/** Internal class holding validation information. */
59
private static final class ValidateInfo {
60
/** Name of the attribute to look for. */
61
protected String attribute;
63
/** Format of the attribute value, using Regex pattern syntax. */
64
protected String format;
66
/** Indicates if the attribute presence is required. */
67
protected boolean required;
73
* Name of the attribute to look for.
75
* Indicates if the attribute presence is required.
77
* Format of the attribute value, using Regex pattern syntax.
79
public ValidateInfo(String attribute, boolean required, String format) {
80
this.attribute = attribute;
81
this.required = required;
86
/** The list of attribute validations. */
87
private volatile List<ValidateInfo> validations;
102
public Validator(Context context) {
114
public Validator(Context context, Restlet next) {
115
super(context, next);
119
* Allows filtering before its handling by the target Restlet. By default it
120
* parses the template variable, adjust the base reference, then extracts
121
* the attributes from form parameters (query, cookies, entity) and finally
122
* tries to validate the variables as indicated by the
123
* {@link #validate(String, boolean, String)} method.
126
* The request to filter.
128
* The response to filter.
129
* @return The {@link Filter#CONTINUE} status.
132
protected int beforeHandle(Request request, Response response) {
133
if (this.validations != null) {
134
for (ValidateInfo validate : getValidations()) {
135
if (validate.required
136
&& !request.getAttributes().containsKey(
137
validate.attribute)) {
140
Status.CLIENT_ERROR_BAD_REQUEST,
141
"Unable to find the \""
143
+ "\" attribute in the request. Please check your request.");
144
} else if (validate.format != null) {
145
Object value = request.getAttributes().get(
149
&& !Pattern.matches(validate.format, value
153
Status.CLIENT_ERROR_BAD_REQUEST,
154
"Unable to validate the value of the \""
156
+ "\" attribute. The expected format is: "
158
+ " (Java Regex). Please check your request.");
168
* Returns the list of attribute validations.
170
* @return The list of attribute validations.
172
private List<ValidateInfo> getValidations() {
173
// Lazy initialization with double-check.
174
List<ValidateInfo> v = this.validations;
176
synchronized (this) {
177
v = this.validations;
179
this.validations = v = new CopyOnWriteArrayList<ValidateInfo>();
187
* Checks the request attributes for presence or format. If the check fails,
188
* then a response status CLIENT_ERROR_BAD_REQUEST is returned with the
189
* proper status description.
192
* Name of the attribute to look for.
194
* Indicates if the attribute presence is required.
196
* Format of the attribute value, using Regex pattern syntax.
198
public void validate(String attribute, boolean required, String format) {
199
getValidations().add(new ValidateInfo(attribute, required, format));
203
* Checks the request attributes for format only. If the check fails, then a
204
* response status CLIENT_ERROR_BAD_REQUEST is returned with the proper
205
* status description.
208
* Name of the attribute to look for.
210
* Format of the attribute value, using Regex pattern syntax.
212
public void validateFormat(String attribute, String format) {
213
getValidations().add(new ValidateInfo(attribute, false, format));
217
* Checks the request attributes for presence only. If the check fails, then
218
* a response status CLIENT_ERROR_BAD_REQUEST is returned with the proper
219
* status description.
222
* Name of the attribute to look for.
224
public void validatePresence(String attribute) {
225
getValidations().add(new ValidateInfo(attribute, true, null));