1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.extensions.validator.core.storage;
20
21 import org.apache.myfaces.extensions.validator.core.ExtValCoreConfiguration;
22 import org.apache.myfaces.extensions.validator.internal.UsageInformation;
23 import org.apache.myfaces.extensions.validator.internal.ToDo;
24 import org.apache.myfaces.extensions.validator.internal.Priority;
25 import static org.apache.myfaces.extensions.validator.internal.UsageCategory.INTERNAL;
26 import org.apache.myfaces.extensions.validator.core.property.PropertyInformation;
27 import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
28 import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
29 import org.apache.myfaces.extensions.validator.core.property.DefaultPropertyInformation;
30 import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
31 import org.apache.myfaces.extensions.validator.core.CustomInformation;
32 import org.apache.myfaces.extensions.validator.core.ExtValContext;
33 import org.apache.myfaces.extensions.validator.util.ClassUtils;
34 import org.apache.myfaces.extensions.validator.util.ProxyUtils;
35 import org.apache.myfaces.extensions.validator.util.NullValueAwareConcurrentHashMap;
36
37 import java.util.Map;
38 import java.util.List;
39 import java.util.ArrayList;
40 import java.util.concurrent.ConcurrentHashMap;
41 import java.util.concurrent.CopyOnWriteArrayList;
42 import java.util.logging.Logger;
43
44
45
46
47 @UsageInformation(INTERNAL)
48 public class DefaultMetaDataStorage implements MetaDataStorage
49 {
50 protected final Logger logger = Logger.getLogger(getClass().getName());
51
52 private Map<String, Map<String, PropertyInformation>> cachedPropertyInformation =
53 new ConcurrentHashMap<String, Map<String, PropertyInformation>>();
54
55 private List<MetaDataStorageFilter> metaDataStorageFilters = new CopyOnWriteArrayList<MetaDataStorageFilter>();
56 private List<Class<? extends MetaDataStorageFilter>> deniedMetaDataFilters =
57 new CopyOnWriteArrayList<Class<? extends MetaDataStorageFilter>>();
58
59 public DefaultMetaDataStorage()
60 {
61 initFilters();
62 }
63
64 private void initFilters()
65 {
66 List<String> metaDataStorageFilterClassNames = new ArrayList<String>();
67
68 metaDataStorageFilterClassNames
69 .add(ExtValCoreConfiguration.get().customMetaDataStorageFilterClassName());
70 metaDataStorageFilterClassNames
71 .add(ExtValContext.getContext().getInformationProviderBean().get(
72 CustomInformation.META_DATA_STORAGE_FILTER));
73
74 MetaDataStorageFilter metaDataStorageFilter;
75 for (String validationExceptionInterceptorName : metaDataStorageFilterClassNames)
76 {
77 metaDataStorageFilter =
78 (MetaDataStorageFilter)ClassUtils.tryToInstantiateClassForName(validationExceptionInterceptorName);
79
80 if (metaDataStorageFilter != null)
81 {
82 this.metaDataStorageFilters.add(metaDataStorageFilter);
83
84 logAddedFilter(metaDataStorageFilter.getClass());
85 }
86 }
87 }
88
89 public void storeMetaDataOf(PropertyInformation propertyInformation)
90 {
91 invokeFilters(propertyInformation);
92
93 PropertyInformation propertyInformationToStore = new DefaultPropertyInformation();
94
95 PropertyDetails propertyDetails = propertyInformation
96 .getInformation(PropertyInformationKeys.PROPERTY_DETAILS, PropertyDetails.class);
97
98 copyMetaData(propertyInformation, propertyInformationToStore);
99
100 getMapForClass(ProxyUtils.getUnproxiedClass(propertyDetails.getBaseObject().getClass()))
101 .put(propertyDetails.getProperty(), propertyInformationToStore);
102 }
103
104 private void invokeFilters(PropertyInformation propertyInformation)
105 {
106 for(MetaDataStorageFilter filter : this.metaDataStorageFilters)
107 {
108 filter.filter(propertyInformation);
109 }
110 }
111
112 public MetaDataEntry[] getMetaData(Class targetClass, String targetProperty)
113 {
114 PropertyInformation propertyInformation = getMapForClass(targetClass).get(targetProperty);
115
116 PropertyInformation clonedPropertyInformation = new DefaultPropertyInformation();
117 copyMetaData(propertyInformation, clonedPropertyInformation);
118
119 return clonedPropertyInformation.getMetaDataEntries();
120 }
121
122 public boolean containsMetaDataFor(Class targetClass, String targetProperty)
123 {
124 return getMapForClass(targetClass).containsKey(targetProperty);
125 }
126
127 public void registerFilter(MetaDataStorageFilter storageFilter)
128 {
129 synchronized (this)
130 {
131 if(!isFilterDenied(storageFilter) && !isFilterAlreadyRegistered(storageFilter))
132 {
133 this.metaDataStorageFilters.add(storageFilter);
134 logAddedFilter(storageFilter.getClass());
135 }
136 }
137 }
138
139 private boolean isFilterDenied(MetaDataStorageFilter storageFilter)
140 {
141 return this.deniedMetaDataFilters.contains(getStorageFilterClass(storageFilter));
142 }
143
144 private boolean isFilterAlreadyRegistered(MetaDataStorageFilter storageFilter)
145 {
146 for(MetaDataStorageFilter filter : this.metaDataStorageFilters)
147 {
148 if(filter.getClass().equals(getStorageFilterClass(storageFilter)))
149 {
150 return true;
151 }
152 }
153 return false;
154 }
155
156 public void deregisterFilter(Class<? extends MetaDataStorageFilter> filterClass)
157 {
158 MetaDataStorageFilter storageFilter = ClassUtils.tryToInstantiateClass(filterClass);
159
160 synchronized (this)
161 {
162 this.metaDataStorageFilters.remove(storageFilter);
163 }
164
165 logRemovedFilter(storageFilter.getClass());
166 }
167
168 public void denyFilter(Class<? extends MetaDataStorageFilter> filterClass)
169 {
170 synchronized (this)
171 {
172 for(Class<? extends MetaDataStorageFilter> filterId : this.deniedMetaDataFilters)
173 {
174 if(filterId.equals(filterClass))
175 {
176 return;
177 }
178 }
179 this.deniedMetaDataFilters.add(filterClass);
180 }
181
182 deregisterFilter(filterClass);
183 }
184
185 @ToDo(Priority.MEDIUM)
186 private void copyMetaData(PropertyInformation source, PropertyInformation target)
187 {
188 MetaDataEntry newMetaDataEntry;
189 for(MetaDataEntry metaDataEntry : source.getMetaDataEntries())
190 {
191 newMetaDataEntry = new MetaDataEntry();
192 newMetaDataEntry.setKey(metaDataEntry.getKey());
193 newMetaDataEntry.setValue(metaDataEntry.getValue());
194
195 target.addMetaDataEntry(newMetaDataEntry);
196 }
197 }
198
199 private void logAddedFilter(Class<? extends MetaDataStorageFilter> filterClass)
200 {
201 this.logger.info(filterClass.getName() + " added");
202 }
203
204 private void logRemovedFilter(Class<? extends MetaDataStorageFilter> filterClass)
205 {
206 this.logger.info(filterClass.getName() + " removed");
207 }
208
209 private Map<String, PropertyInformation> getMapForClass(Class target)
210 {
211 String key = ProxyUtils.getClassName(target);
212 if(!this.cachedPropertyInformation.containsKey(key))
213 {
214 this.cachedPropertyInformation.put(key,
215 new NullValueAwareConcurrentHashMap<String, PropertyInformation>(new NullMarkerPropertyInformation()));
216 }
217 return this.cachedPropertyInformation.get(key);
218 }
219
220 private static class NullMarkerPropertyInformation implements PropertyInformation
221 {
222 public boolean containsInformation(String key)
223 {
224 throw new UnsupportedOperationException();
225 }
226
227 public Object getInformation(String key)
228 {
229 throw new UnsupportedOperationException();
230 }
231
232 public <T> T getInformation(String key, Class<T> targetClass)
233 {
234 throw new UnsupportedOperationException();
235 }
236
237 public void setInformation(String key, Object value)
238 {
239 throw new UnsupportedOperationException();
240 }
241
242 public MetaDataEntry[] getMetaDataEntries()
243 {
244 throw new UnsupportedOperationException();
245 }
246
247 public void addMetaDataEntry(MetaDataEntry metaDataEntry)
248 {
249 throw new UnsupportedOperationException();
250 }
251
252 public void resetMetaDataEntries()
253 {
254 throw new UnsupportedOperationException();
255 }
256
257 @Override
258 public int hashCode()
259 {
260 return getClass().hashCode();
261 }
262
263 @Override
264 public boolean equals(Object target)
265 {
266 return target != null && getClass().equals(target.getClass());
267 }
268 }
269
270 private Class<? extends MetaDataStorageFilter> getStorageFilterClass(MetaDataStorageFilter storageFilter)
271 {
272 return ProxyUtils.getUnproxiedClass(storageFilter.getClass(), MetaDataStorageFilter.class);
273 }
274 }