001 // Copyright 2004, 2005 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry.valid;
016
017 import java.net.MalformedURLException;
018 import java.net.URL;
019 import java.util.Collection;
020 import java.util.HashMap;
021 import java.util.Iterator;
022 import java.util.Locale;
023 import java.util.Map;
024 import java.util.ResourceBundle;
025 import java.util.Vector;
026
027 import org.apache.tapestry.IMarkupWriter;
028 import org.apache.tapestry.IRequestCycle;
029 import org.apache.tapestry.form.IFormComponent;
030 import org.apache.tapestry.util.StringSplitter;
031
032 /**
033 * @since 3.0
034 */
035 public class UrlValidator extends BaseValidator
036 {
037 private int _minimumLength;
038
039 private String _minimumLengthMessage;
040
041 private String _invalidUrlFormatMessage;
042
043 private String _disallowedProtocolMessage;
044
045 private Collection _allowedProtocols;
046
047 private String _scriptPath = "/org/apache/tapestry/valid/UrlValidator.script"; //$NON-NLS-1$
048
049 public UrlValidator()
050 {
051 }
052
053 /**
054 * Initializes the UrlValidator with properties defined by the initializer.
055 *
056 * @since 4.0
057 */
058
059 public UrlValidator(String initializer)
060 {
061 super(initializer);
062 }
063
064 public String toString(IFormComponent field, Object value)
065 {
066 if (value == null)
067 return null;
068
069 return value.toString();
070 }
071
072 public Object toObject(IFormComponent field, String input) throws ValidatorException
073 {
074 if (checkRequired(field, input))
075 return null;
076
077 if (_minimumLength > 0 && input.length() < _minimumLength)
078 throw new ValidatorException(buildMinimumLengthMessage(field),
079 ValidationConstraint.MINIMUM_WIDTH);
080
081 if (!isValidUrl(input))
082 throw new ValidatorException(buildInvalidUrlFormatMessage(field),
083 ValidationConstraint.URL_FORMAT);
084
085 if (!isAllowedProtocol(input))
086 {
087 throw new ValidatorException(buildDisallowedProtocolMessage(field),
088 ValidationConstraint.DISALLOWED_PROTOCOL);
089 }
090
091 return input;
092 }
093
094 public int getMinimumLength()
095 {
096 return _minimumLength;
097 }
098
099 public void setMinimumLength(int minimumLength)
100 {
101 _minimumLength = minimumLength;
102 }
103
104 public void renderValidatorContribution(IFormComponent field, IMarkupWriter writer,
105 IRequestCycle cycle)
106 {
107 if (!isClientScriptingEnabled())
108 return;
109
110 Map symbols = new HashMap();
111
112 if (isRequired())
113 symbols.put("requiredMessage", buildRequiredMessage(field)); //$NON-NLS-1$
114
115 if (_minimumLength > 0)
116 symbols.put("minimumLengthMessage", //$NON-NLS-1$
117 buildMinimumLengthMessage(field));
118
119 symbols.put("urlFormatMessage", buildInvalidUrlFormatMessage(field)); //$NON-NLS-1$
120
121 symbols.put("urlDisallowedProtocolMessage", //$NON-NLS-1$
122 buildDisallowedProtocolMessage(field));
123
124 symbols.put("urlRegexpProtocols", buildUrlRegexpProtocols()); //$NON-NLS-1$
125
126 processValidatorScript(_scriptPath, cycle, field, symbols);
127 }
128
129 private String buildUrlRegexpProtocols()
130 {
131 if (_allowedProtocols == null)
132 {
133 return null;
134 }
135 String regexp = "/("; //$NON-NLS-1$
136 Iterator iter = _allowedProtocols.iterator();
137 while (iter.hasNext())
138 {
139 String protocol = (String) iter.next();
140 regexp += protocol;
141 if (iter.hasNext())
142 {
143 regexp += "|"; //$NON-NLS-1$
144 }
145 }
146 regexp += "):///"; //$NON-NLS-1$
147 return regexp;
148 }
149
150 public String getScriptPath()
151 {
152 return _scriptPath;
153 }
154
155 public void setScriptPath(String scriptPath)
156 {
157 _scriptPath = scriptPath;
158 }
159
160 protected boolean isValidUrl(String url)
161 {
162 boolean bIsValid;
163 try
164 {
165 new URL(url);
166 bIsValid = true;
167 }
168 catch (MalformedURLException mue)
169 {
170 bIsValid = false;
171 }
172 return bIsValid;
173 }
174
175 protected boolean isAllowedProtocol(String url)
176 {
177 boolean bIsAllowed = false;
178 if (_allowedProtocols != null)
179 {
180 URL oUrl;
181 try
182 {
183 oUrl = new URL(url);
184 }
185 catch (MalformedURLException e)
186 {
187 return false;
188 }
189 String actualProtocol = oUrl.getProtocol();
190 Iterator iter = _allowedProtocols.iterator();
191 while (iter.hasNext())
192 {
193 String protocol = (String) iter.next();
194 if (protocol.equals(actualProtocol))
195 {
196 bIsAllowed = true;
197 break;
198 }
199 }
200 }
201 else
202 {
203 bIsAllowed = true;
204 }
205 return bIsAllowed;
206 }
207
208 public String getInvalidUrlFormatMessage()
209 {
210 return _invalidUrlFormatMessage;
211 }
212
213 public String getMinimumLengthMessage()
214 {
215 return _minimumLengthMessage;
216 }
217
218 public void setInvalidUrlFormatMessage(String string)
219 {
220 _invalidUrlFormatMessage = string;
221 }
222
223 public String getDisallowedProtocolMessage()
224 {
225 return _disallowedProtocolMessage;
226 }
227
228 public void setDisallowedProtocolMessage(String string)
229 {
230 _disallowedProtocolMessage = string;
231 }
232
233 public void setMinimumLengthMessage(String string)
234 {
235 _minimumLengthMessage = string;
236 }
237
238 protected String buildMinimumLengthMessage(IFormComponent field)
239 {
240 String pattern = getPattern(_minimumLengthMessage, "field-too-short", //$NON-NLS-1$
241 field.getPage().getLocale());
242
243 return formatString(pattern, Integer.toString(_minimumLength), field.getDisplayName());
244 }
245
246 protected String buildInvalidUrlFormatMessage(IFormComponent field)
247 {
248 String pattern = getPattern(_invalidUrlFormatMessage, "invalid-url-format", //$NON-NLS-1$
249 field.getPage().getLocale());
250
251 return formatString(pattern, field.getDisplayName());
252 }
253
254 protected String buildDisallowedProtocolMessage(IFormComponent field)
255 {
256 if (_allowedProtocols == null)
257 {
258 return null;
259 }
260 String pattern = getPattern(_disallowedProtocolMessage, "disallowed-protocol", //$NON-NLS-1$
261 field.getPage().getLocale());
262
263 String allowedProtocols = ""; //$NON-NLS-1$
264 Iterator iter = _allowedProtocols.iterator();
265 while (iter.hasNext())
266 {
267 String protocol = (String) iter.next();
268 if (!allowedProtocols.equals("")) { //$NON-NLS-1$
269 if (iter.hasNext())
270 {
271 allowedProtocols += ", "; //$NON-NLS-1$
272 }
273 else
274 {
275 allowedProtocols += " or "; //$NON-NLS-1$
276 }
277 }
278 allowedProtocols += protocol;
279 }
280
281 return formatString(pattern, allowedProtocols);
282 }
283
284 protected String getPattern(String override, String key, Locale locale)
285 {
286 if (override != null)
287 return override;
288
289 ResourceBundle strings = ResourceBundle.getBundle(
290 "org.apache.tapestry.valid.ValidationStrings",
291 locale);
292 return strings.getString(key);
293 }
294
295 /**
296 * @param protocols
297 * comma separated list of allowed protocols
298 */
299 public void setAllowedProtocols(String protocols)
300 {
301 StringSplitter spliter = new StringSplitter(',');
302 // String[] aProtocols = protocols.split(","); //$NON-NLS-1$
303 String[] aProtocols = spliter.splitToArray(protocols); //$NON-NLS-1$
304 _allowedProtocols = new Vector();
305 for (int i = 0; i < aProtocols.length; i++)
306 {
307 _allowedProtocols.add(aProtocols[i]);
308 }
309 }
310
311 }