~ubuntu-branches/ubuntu/saucy/restlet/saucy

« back to all changes in this revision

Viewing changes to org.restlet/src/org/restlet/routing/Validator.java

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-06-11 16:25:45 UTC
  • Revision ID: package-import@ubuntu.com-20120611162545-5w2o0resi5y3pybc
Tags: upstream-2.0.14
ImportĀ upstreamĀ versionĀ 2.0.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Copyright 2005-2012 Restlet S.A.S.
 
3
 * 
 
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.
 
8
 * 
 
9
 * You can obtain a copy of the Apache 2.0 license at
 
10
 * http://www.opensource.org/licenses/apache-2.0
 
11
 * 
 
12
 * You can obtain a copy of the LGPL 3.0 license at
 
13
 * http://www.opensource.org/licenses/lgpl-3.0
 
14
 * 
 
15
 * You can obtain a copy of the LGPL 2.1 license at
 
16
 * http://www.opensource.org/licenses/lgpl-2.1
 
17
 * 
 
18
 * You can obtain a copy of the CDDL 1.0 license at
 
19
 * http://www.opensource.org/licenses/cddl1
 
20
 * 
 
21
 * You can obtain a copy of the EPL 1.0 license at
 
22
 * http://www.opensource.org/licenses/eclipse-1.0
 
23
 * 
 
24
 * See the Licenses for the specific language governing permissions and
 
25
 * limitations under the Licenses.
 
26
 * 
 
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
 
30
 * 
 
31
 * Restlet is a registered trademark of Restlet S.A.S.
 
32
 */
 
33
 
 
34
package org.restlet.routing;
 
35
 
 
36
import java.util.List;
 
37
import java.util.concurrent.CopyOnWriteArrayList;
 
38
import java.util.regex.Pattern;
 
39
 
 
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;
 
45
 
 
46
/**
 
47
 * Filter validating attributes from a call. Validation is verified based on
 
48
 * regex pattern matching.<br>
 
49
 * <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.
 
53
 * 
 
54
 * @author Jerome Louvel
 
55
 * @see Pattern
 
56
 */
 
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;
 
62
 
 
63
        /** Format of the attribute value, using Regex pattern syntax. */
 
64
        protected String format;
 
65
 
 
66
        /** Indicates if the attribute presence is required. */
 
67
        protected boolean required;
 
68
 
 
69
        /**
 
70
         * Constructor.
 
71
         * 
 
72
         * @param attribute
 
73
         *            Name of the attribute to look for.
 
74
         * @param required
 
75
         *            Indicates if the attribute presence is required.
 
76
         * @param format
 
77
         *            Format of the attribute value, using Regex pattern syntax.
 
78
         */
 
79
        public ValidateInfo(String attribute, boolean required, String format) {
 
80
            this.attribute = attribute;
 
81
            this.required = required;
 
82
            this.format = format;
 
83
        }
 
84
    }
 
85
 
 
86
    /** The list of attribute validations. */
 
87
    private volatile List<ValidateInfo> validations;
 
88
 
 
89
    /**
 
90
     * Constructor.
 
91
     */
 
92
    public Validator() {
 
93
        this(null);
 
94
    }
 
95
 
 
96
    /**
 
97
     * Constructor.
 
98
     * 
 
99
     * @param context
 
100
     *            The context.
 
101
     */
 
102
    public Validator(Context context) {
 
103
        this(context, null);
 
104
    }
 
105
 
 
106
    /**
 
107
     * Constructor.
 
108
     * 
 
109
     * @param context
 
110
     *            The context.
 
111
     * @param next
 
112
     *            The next Restlet.
 
113
     */
 
114
    public Validator(Context context, Restlet next) {
 
115
        super(context, next);
 
116
    }
 
117
 
 
118
    /**
 
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.
 
124
     * 
 
125
     * @param request
 
126
     *            The request to filter.
 
127
     * @param response
 
128
     *            The response to filter.
 
129
     * @return The {@link Filter#CONTINUE} status.
 
130
     */
 
131
    @Override
 
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)) {
 
138
                    response
 
139
                            .setStatus(
 
140
                                    Status.CLIENT_ERROR_BAD_REQUEST,
 
141
                                    "Unable to find the \""
 
142
                                            + validate.attribute
 
143
                                            + "\" attribute in the request. Please check your request.");
 
144
                } else if (validate.format != null) {
 
145
                    Object value = request.getAttributes().get(
 
146
                            validate.attribute);
 
147
 
 
148
                    if ((value != null)
 
149
                            && !Pattern.matches(validate.format, value
 
150
                                    .toString())) {
 
151
                        response
 
152
                                .setStatus(
 
153
                                        Status.CLIENT_ERROR_BAD_REQUEST,
 
154
                                        "Unable to validate the value of the \""
 
155
                                                + validate.attribute
 
156
                                                + "\" attribute. The expected format is: "
 
157
                                                + validate.format
 
158
                                                + " (Java Regex). Please check your request.");
 
159
                    }
 
160
                }
 
161
            }
 
162
        }
 
163
 
 
164
        return CONTINUE;
 
165
    }
 
166
 
 
167
    /**
 
168
     * Returns the list of attribute validations.
 
169
     * 
 
170
     * @return The list of attribute validations.
 
171
     */
 
172
    private List<ValidateInfo> getValidations() {
 
173
        // Lazy initialization with double-check.
 
174
        List<ValidateInfo> v = this.validations;
 
175
        if (v == null) {
 
176
            synchronized (this) {
 
177
                v = this.validations;
 
178
                if (v == null) {
 
179
                    this.validations = v = new CopyOnWriteArrayList<ValidateInfo>();
 
180
                }
 
181
            }
 
182
        }
 
183
        return v;
 
184
    }
 
185
 
 
186
    /**
 
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.
 
190
     * 
 
191
     * @param attribute
 
192
     *            Name of the attribute to look for.
 
193
     * @param required
 
194
     *            Indicates if the attribute presence is required.
 
195
     * @param format
 
196
     *            Format of the attribute value, using Regex pattern syntax.
 
197
     */
 
198
    public void validate(String attribute, boolean required, String format) {
 
199
        getValidations().add(new ValidateInfo(attribute, required, format));
 
200
    }
 
201
 
 
202
    /**
 
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.
 
206
     * 
 
207
     * @param attribute
 
208
     *            Name of the attribute to look for.
 
209
     * @param format
 
210
     *            Format of the attribute value, using Regex pattern syntax.
 
211
     */
 
212
    public void validateFormat(String attribute, String format) {
 
213
        getValidations().add(new ValidateInfo(attribute, false, format));
 
214
    }
 
215
 
 
216
    /**
 
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.
 
220
     * 
 
221
     * @param attribute
 
222
     *            Name of the attribute to look for.
 
223
     */
 
224
    public void validatePresence(String attribute) {
 
225
        getValidations().add(new ValidateInfo(attribute, true, null));
 
226
    }
 
227
}