1 package org.apache.struts2.oval.interceptor;
2
3 import com.opensymphony.xwork2.inject.Inject;
4 import com.opensymphony.xwork2.util.FileManager;
5 import com.opensymphony.xwork2.util.logging.Logger;
6 import com.opensymphony.xwork2.util.logging.LoggerFactory;
7 import net.sf.oval.configuration.Configurer;
8 import net.sf.oval.configuration.annotation.AnnotationsConfigurer;
9 import net.sf.oval.configuration.annotation.JPAAnnotationsConfigurer;
10 import net.sf.oval.configuration.xml.XMLConfigurer;
11
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.TreeSet;
18
19
20 public class DefaultOValValidationManager implements OValValidationManager {
21 private static final Logger LOG = LoggerFactory.getLogger(DefaultOValValidationManager.class);
22
23 protected static final String VALIDATION_CONFIG_SUFFIX = "-validation.xml";
24 protected final Map<String, List<Configurer>> validatorCache = new HashMap<String, List<Configurer>>();
25 protected final Map<String, Configurer> validatorFileCache = new HashMap<String, Configurer>();
26
27 protected boolean validateJPAAnnotations;
28
29 public synchronized List<Configurer> getConfigurers(Class clazz, String context, boolean validateJPAAnnotations) {
30 this.validateJPAAnnotations =validateJPAAnnotations;
31 final String validatorKey = buildValidatorKey(clazz, context);
32
33 if (validatorCache.containsKey(validatorKey)) {
34 if (FileManager.isReloadingConfigs()) {
35 List<Configurer> configurers = buildXMLConfigurers(clazz, context, true, null);
36
37
38 addAditionalConfigurers(configurers);
39 validatorCache.put(validatorKey, configurers);
40 }
41 } else {
42 List<Configurer> configurers = buildXMLConfigurers(clazz, context, false, null);
43
44
45 addAditionalConfigurers(configurers);
46 validatorCache.put(validatorKey, configurers);
47 }
48
49
50 return validatorCache.get(validatorKey);
51 }
52
53 private void addAditionalConfigurers(List<Configurer> configurers) {
54 AnnotationsConfigurer annotationsConfigurer = new AnnotationsConfigurer();
55 configurers.add(annotationsConfigurer);
56
57 if (validateJPAAnnotations) {
58 if (LOG.isDebugEnabled())
59 LOG.debug("Adding support for JPA annotations validations in OVal");
60 configurers.add(new JPAAnnotationsConfigurer());
61 }
62 }
63
64 protected static String buildValidatorKey(Class clazz, String context) {
65 StringBuilder sb = new StringBuilder(clazz.getName());
66 sb.append("/");
67 sb.append(context);
68 return sb.toString();
69 }
70
71 private List<Configurer> buildXMLConfigurers(Class clazz, String context, boolean checkFile, Set<String> checked) {
72 List<Configurer> configurers = new ArrayList<Configurer>();
73
74 if (checked == null) {
75 checked = new TreeSet<String>();
76 } else if (checked.contains(clazz.getName())) {
77 return configurers;
78 }
79
80 if (clazz.isInterface()) {
81 for (Class anInterface : clazz.getInterfaces()) {
82 configurers.addAll(buildXMLConfigurers(anInterface, context, checkFile, checked));
83 }
84 } else {
85 if (!clazz.equals(Object.class)) {
86 configurers.addAll(buildXMLConfigurers(clazz.getSuperclass(), context, checkFile, checked));
87 }
88 }
89
90
91 for (Class anInterface1 : clazz.getInterfaces()) {
92 if (checked.contains(anInterface1.getName())) {
93 continue;
94 }
95
96 addIfNotNull(configurers, buildClassValidatorConfigs(anInterface1, checkFile));
97
98 if (context != null) {
99 addIfNotNull(configurers, buildAliasValidatorConfigs(anInterface1, context, checkFile));
100 }
101
102 checked.add(anInterface1.getName());
103 }
104
105 addIfNotNull(configurers, buildClassValidatorConfigs(clazz, checkFile));
106
107 if (context != null) {
108 addIfNotNull(configurers, buildAliasValidatorConfigs(clazz, context, checkFile));
109 }
110
111 checked.add(clazz.getName());
112
113 return configurers;
114 }
115
116 protected void addIfNotNull(List<Configurer> configurers, Configurer configurer) {
117 if (configurer != null)
118 configurers.add(configurer);
119 }
120
121
122 protected XMLConfigurer buildAliasValidatorConfigs(Class aClass, String context, boolean checkFile) {
123 String fileName = aClass.getName().replace('.', '/') + "-" + context + VALIDATION_CONFIG_SUFFIX;
124
125 return loadFile(fileName, aClass, checkFile);
126 }
127
128 protected XMLConfigurer buildClassValidatorConfigs(Class aClass, boolean checkFile) {
129 String fileName = aClass.getName().replace('.', '/') + VALIDATION_CONFIG_SUFFIX;
130
131 return loadFile(fileName, aClass, checkFile);
132 }
133
134 protected XMLConfigurer loadFile(String fileName, Class clazz, boolean checkFile) {
135 if ((checkFile && FileManager.fileNeedsReloading(fileName, clazz)) || !validatorFileCache.containsKey(fileName)) {
136 java.io.InputStream is = null;
137
138 try {
139 is = FileManager.loadFile(fileName, clazz);
140
141 if (is != null) {
142 if (LOG.isDebugEnabled())
143 LOG.debug("Loading validation xml file [#0]", fileName);
144 XMLConfigurer configurer = new XMLConfigurer();
145 configurer.fromXML(is);
146 validatorFileCache.put(fileName, configurer);
147 return configurer;
148 }
149 } finally {
150 if (is != null) {
151 try {
152 is.close();
153 } catch (java.io.IOException e) {
154 LOG.error("Unable to close input stream for [#0] ", e, fileName);
155 }
156 }
157 }
158 } else {
159 return (XMLConfigurer) validatorFileCache.get(fileName);
160 }
161
162 return null;
163 }
164 }