1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.validator;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.Serializable;
22 import java.net.URL;
23 import java.util.Collections;
24 import java.util.Locale;
25 import java.util.Map;
26
27 import org.apache.commons.collections.FastHashMap;
28 import org.apache.commons.digester.Digester;
29 import org.apache.commons.digester.Rule;
30 import org.apache.commons.digester.xmlrules.DigesterLoader;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.xml.sax.Attributes;
34 import org.xml.sax.SAXException;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class ValidatorResources implements Serializable {
54
55 private static final long serialVersionUID = -8203745881446239554L;
56
57
58 private static final String VALIDATOR_RULES = "digester-rules.xml";
59
60
61
62
63
64
65 private static final String[] REGISTRATIONS = {
66 "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN",
67 "/org/apache/commons/validator/resources/validator_1_0.dtd",
68 "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0.1//EN",
69 "/org/apache/commons/validator/resources/validator_1_0_1.dtd",
70 "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1//EN",
71 "/org/apache/commons/validator/resources/validator_1_1.dtd",
72 "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN",
73 "/org/apache/commons/validator/resources/validator_1_1_3.dtd",
74 "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.2.0//EN",
75 "/org/apache/commons/validator/resources/validator_1_2_0.dtd",
76 "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.3.0//EN",
77 "/org/apache/commons/validator/resources/validator_1_3_0.dtd",
78 "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.4.0//EN",
79 "/org/apache/commons/validator/resources/validator_1_4_0.dtd"
80 };
81
82
83
84
85 protected static Locale defaultLocale = Locale.getDefault();
86
87 private static final String ARGS_PATTERN
88 = "form-validation/formset/form/field/arg";
89
90 private transient Log log = LogFactory.getLog(ValidatorResources.class);
91
92
93
94
95
96
97 @Deprecated
98 protected FastHashMap hFormSets = new FastHashMap();
99
100
101
102
103
104
105 @Deprecated
106 protected FastHashMap hConstants = new FastHashMap();
107
108
109
110
111
112
113 @Deprecated
114 protected FastHashMap hActions = new FastHashMap();
115
116
117
118
119
120 protected FormSet defaultFormSet;
121
122
123
124
125 public ValidatorResources() {
126 }
127
128
129
130
131
132
133
134
135
136
137
138 public ValidatorResources(final InputStream in) throws IOException, SAXException {
139 this(new InputStream[]{in});
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153 public ValidatorResources(final InputStream[] streams)
154 throws IOException, SAXException {
155
156 final Digester digester = initDigester();
157 for (int i = 0; i < streams.length; i++) {
158 if (streams[i] == null) {
159 throw new IllegalArgumentException("Stream[" + i + "] is null");
160 }
161 digester.push(this);
162 digester.parse(streams[i]);
163 }
164
165 this.process();
166 }
167
168
169
170
171
172
173
174
175
176
177 public ValidatorResources(final String uri) throws IOException, SAXException {
178 this(new String[] { uri });
179 }
180
181
182
183
184
185
186
187
188
189
190
191 public ValidatorResources(final String... uris)
192 throws IOException, SAXException {
193
194 final Digester digester = initDigester();
195 for (final String element : uris) {
196 digester.push(this);
197 digester.parse(element);
198 }
199
200 this.process();
201 }
202
203
204
205
206
207
208
209
210
211
212
213 public ValidatorResources(final URL url)
214 throws IOException, SAXException {
215 this(new URL[]{url});
216 }
217
218
219
220
221
222
223
224
225
226
227
228 public ValidatorResources(final URL[] urls)
229 throws IOException, SAXException {
230
231 final Digester digester = initDigester();
232 for (final URL url : urls) {
233 digester.push(this);
234 digester.parse(url);
235 }
236
237 this.process();
238 }
239
240
241
242
243
244
245 public void addConstant(final String name, final String value) {
246 if (getLog().isDebugEnabled()) {
247 getLog().debug("Adding Global Constant: " + name + "," + value);
248 }
249
250 this.hConstants.put(name, value);
251 }
252
253
254
255
256
257
258
259
260 public void addFormSet(final FormSet fs) {
261 final String key = this.buildKey(fs);
262 if (key.isEmpty()) {
263 if (getLog().isWarnEnabled() && defaultFormSet != null) {
264
265 getLog().warn("Overriding default FormSet definition.");
266 }
267 defaultFormSet = fs;
268 } else {
269 final FormSet formset = getFormSets().get(key);
270 if (formset == null) {
271 if (getLog().isDebugEnabled()) {
272 getLog().debug("Adding FormSet '" + fs + "'.");
273 }
274 } else if (getLog().isWarnEnabled()) {
275
276 getLog().warn("Overriding FormSet definition. Duplicate for locale: " + key);
277 }
278 getFormSets().put(key, fs);
279 }
280 }
281
282
283
284
285
286
287
288 private void addOldArgRules(final Digester digester) {
289
290 final Rule rule = new Rule() {
291 @Override
292 public void begin(final String namespace, final String name, final Attributes attributes) {
293
294 final Arg arg = new Arg();
295 arg.setKey(attributes.getValue("key"));
296 arg.setName(attributes.getValue("name"));
297 if ("false".equalsIgnoreCase(attributes.getValue("resource"))) {
298 arg.setResource(false);
299 }
300 try {
301 final int length = "arg".length();
302 arg.setPosition(Integer.parseInt(name.substring(length)));
303 } catch (final Exception ex) {
304 getLog().error("Error parsing Arg position: " + name + " " + arg + " " + ex);
305 }
306
307
308 ((Field) getDigester().peek(0)).addArg(arg);
309 }
310 };
311
312
313 digester.addRule(ARGS_PATTERN + "0", rule);
314 digester.addRule(ARGS_PATTERN + "1", rule);
315 digester.addRule(ARGS_PATTERN + "2", rule);
316 digester.addRule(ARGS_PATTERN + "3", rule);
317
318 }
319
320
321
322
323
324
325
326
327 public void addValidatorAction(final ValidatorAction va) {
328 va.init();
329
330 getActions().put(va.getName(), va);
331
332 if (getLog().isDebugEnabled()) {
333 getLog().debug("Add ValidatorAction: " + va.getName() + "," + va.getClassname());
334 }
335 }
336
337
338
339
340
341
342
343 protected String buildKey(final FormSet fs) {
344 return
345 this.buildLocale(fs.getLanguage(), fs.getCountry(), fs.getVariant());
346 }
347
348
349
350
351 private String buildLocale(final String lang, final String country, final String variant) {
352 final StringBuilder key = new StringBuilder().append(lang != null && !lang.isEmpty() ? lang : "");
353 key.append(country != null && !country.isEmpty() ? "_" + country : "");
354 key.append(variant != null && !variant.isEmpty() ? "_" + variant : "");
355 return key.toString();
356 }
357
358
359
360
361
362
363 @SuppressWarnings("unchecked")
364 protected Map<String, ValidatorAction> getActions() {
365 return hActions;
366 }
367
368
369
370
371
372
373 @SuppressWarnings("unchecked")
374 protected Map<String, String> getConstants() {
375 return hConstants;
376 }
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393 public Form getForm(final Locale locale, final String formKey) {
394 return this.getForm(locale.getLanguage(), locale.getCountry(), locale
395 .getVariant(), formKey);
396 }
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415 public Form getForm(final String language, final String country, final String variant, final String formKey) {
416
417 Form form = null;
418
419
420 String key = this.buildLocale(language, country, variant);
421 if (!key.isEmpty()) {
422 final FormSet formSet = getFormSets().get(key);
423 if (formSet != null) {
424 form = formSet.getForm(formKey);
425 }
426 }
427 final String localeKey = key;
428
429
430 if (form == null) {
431 key = buildLocale(language, country, null);
432 if (!key.isEmpty()) {
433 final FormSet formSet = getFormSets().get(key);
434 if (formSet != null) {
435 form = formSet.getForm(formKey);
436 }
437 }
438 }
439
440
441 if (form == null) {
442 key = buildLocale(language, null, null);
443 if (!key.isEmpty()) {
444 final FormSet formSet = getFormSets().get(key);
445 if (formSet != null) {
446 form = formSet.getForm(formKey);
447 }
448 }
449 }
450
451
452 if (form == null) {
453 form = defaultFormSet.getForm(formKey);
454 key = "default";
455 }
456
457 if (form == null) {
458 if (getLog().isWarnEnabled()) {
459 getLog().warn("Form '" + formKey + "' not found for locale '" + localeKey + "'");
460 }
461 } else if (getLog().isDebugEnabled()) {
462 getLog().debug("Form '" + formKey + "' found in formset '" + key + "' for locale '" + localeKey + "'");
463 }
464
465 return form;
466
467 }
468
469
470
471
472
473
474
475
476
477
478 FormSet getFormSet(final String language, final String country, final String variant) {
479 final String key = buildLocale(language, country, variant);
480 if (key.isEmpty()) {
481 return defaultFormSet;
482 }
483 return getFormSets().get(key);
484 }
485
486
487
488
489
490
491 @SuppressWarnings("unchecked")
492 protected Map<String, FormSet> getFormSets() {
493 return hFormSets;
494 }
495
496
497
498
499
500
501
502
503
504
505
506 private Log getLog() {
507 if (log == null) {
508 log = LogFactory.getLog(ValidatorResources.class);
509 }
510 return log;
511 }
512
513
514
515
516
517
518
519
520
521
522
523 private FormSet getParent(final FormSet fs) {
524
525 FormSet parent = null;
526 if (fs.getType() == FormSet.LANGUAGE_FORMSET) {
527 parent = defaultFormSet;
528 } else if (fs.getType() == FormSet.COUNTRY_FORMSET) {
529 parent = getFormSets().get(buildLocale(fs.getLanguage(), null, null));
530 if (parent == null) {
531 parent = defaultFormSet;
532 }
533 } else if (fs.getType() == FormSet.VARIANT_FORMSET) {
534 parent = getFormSets().get(buildLocale(fs.getLanguage(), fs.getCountry(), null));
535 if (parent == null) {
536 parent = getFormSets().get(buildLocale(fs.getLanguage(), null, null));
537 if (parent == null) {
538 parent = defaultFormSet;
539 }
540 }
541 }
542 return parent;
543 }
544
545
546
547
548
549
550 public ValidatorAction getValidatorAction(final String key) {
551 return getActions().get(key);
552 }
553
554
555
556
557
558 public Map<String, ValidatorAction> getValidatorActions() {
559 return Collections.unmodifiableMap(getActions());
560 }
561
562
563
564
565 private Digester initDigester() {
566 URL rulesUrl = this.getClass().getResource(VALIDATOR_RULES);
567 if (rulesUrl == null) {
568
569 rulesUrl = ValidatorResources.class.getResource(VALIDATOR_RULES);
570 }
571 if (getLog().isDebugEnabled()) {
572 getLog().debug("Loading rules from '" + rulesUrl + "'");
573 }
574 final Digester digester = DigesterLoader.createDigester(rulesUrl);
575 digester.setNamespaceAware(true);
576 digester.setValidating(true);
577 digester.setUseContextClassLoader(true);
578
579
580 addOldArgRules(digester);
581
582
583 for (int i = 0; i < REGISTRATIONS.length; i += 2) {
584 final URL url = this.getClass().getResource(REGISTRATIONS[i + 1]);
585 if (url != null) {
586 digester.register(REGISTRATIONS[i], url.toString());
587 }
588 }
589 return digester;
590 }
591
592
593
594
595
596
597
598
599
600 public void process() {
601 hFormSets.setFast(true);
602 hConstants.setFast(true);
603 hActions.setFast(true);
604
605 this.processForms();
606 }
607
608
609
610
611
612
613 private void processForms() {
614 if (defaultFormSet == null) {
615
616 defaultFormSet = new FormSet();
617 }
618 defaultFormSet.process(getConstants());
619
620 for (final String key : getFormSets().keySet()) {
621 final FormSet fs = getFormSets().get(key);
622 fs.merge(getParent(fs));
623 }
624
625
626 for (final FormSet fs : getFormSets().values()) {
627 if (!fs.isProcessed()) {
628 fs.process(getConstants());
629 }
630 }
631 }
632
633 }