1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.web.bind;
17
18 import org.kuali.rice.krad.uif.view.ViewIndex;
19 import org.kuali.rice.krad.uif.view.ViewModel;
20 import org.springframework.beans.BeanWrapperImpl;
21 import org.springframework.beans.BeansException;
22 import org.springframework.beans.InvalidPropertyException;
23 import org.springframework.beans.PropertyAccessorUtils;
24 import org.springframework.beans.PropertyValue;
25 import org.springframework.util.StringUtils;
26
27 import java.beans.PropertyDescriptor;
28 import java.beans.PropertyEditor;
29 import java.util.ArrayList;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Set;
33
34
35
36
37
38
39
40
41
42
43
44
45 public class UifViewBeanWrapper extends BeanWrapperImpl {
46 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(UifViewBeanWrapper.class);
47
48
49 private ViewModel model;
50
51
52
53 private Set<String> processedProperties;
54
55 public UifViewBeanWrapper(ViewModel model) {
56 super(model);
57
58 this.model = model;
59 this.processedProperties = new HashSet<String>();
60 }
61
62
63
64
65
66
67
68
69 protected void registerEditorFromView(String propertyName) {
70 if (LOG.isDebugEnabled()) {
71 LOG.debug("Attempting to find property editor for property '" + propertyName + "'");
72 }
73
74
75 if (processedProperties.contains(propertyName)) {
76 return;
77 }
78
79
80
81 ViewIndex viewIndex = null;
82 if (model.getView() != null) {
83 viewIndex = model.getView().getViewIndex();
84 } else if (model.getPostedView() != null) {
85 viewIndex = model.getPostedView().getViewIndex();
86 }
87
88
89 if (viewIndex == null) {
90 return;
91 }
92
93 PropertyEditor propertyEditor = null;
94 boolean requiresEncryption = false;
95
96 if (viewIndex.getFieldPropertyEditors().containsKey(propertyName)) {
97 propertyEditor = viewIndex.getFieldPropertyEditors().get(propertyName);
98 } else if (viewIndex.getSecureFieldPropertyEditors().containsKey(propertyName)) {
99 propertyEditor = viewIndex.getSecureFieldPropertyEditors().get(propertyName);
100 requiresEncryption = true;
101 }
102
103 if (propertyEditor != null) {
104 if (LOG.isDebugEnabled()) {
105 LOG.debug("Registering custom editor for property path '" + propertyName
106 + "' and property editor class '" + propertyEditor.getClass().getName() + "'");
107 }
108
109 if (requiresEncryption) {
110 if (LOG.isDebugEnabled()) {
111 LOG.debug("Enabling encryption for custom editor '" + propertyName +
112 "' and property editor class '" + propertyEditor.getClass().getName() + "'");
113 }
114 this.registerCustomEditor(null, propertyName, new UifEncryptionPropertyEditorWrapper(propertyEditor));
115 } else {
116 this.registerCustomEditor(null, propertyName, propertyEditor);
117 }
118 } else if (requiresEncryption) {
119 if (LOG.isDebugEnabled()) {
120 LOG.debug("No custom formatter for property path '" + propertyName
121 + "' but property does require encryption");
122 }
123
124 this.registerCustomEditor(null, propertyName, new UifEncryptionPropertyEditorWrapper(
125 findEditorForPropertyName(propertyName)));
126 }
127
128 processedProperties.add(propertyName);
129 }
130
131 protected PropertyEditor findEditorForPropertyName(String propertyName) {
132 Class<?> clazz = getPropertyType(propertyName);
133 if (LOG.isDebugEnabled()) {
134 LOG.debug("Attempting retrieval of property editor using class '"
135 + clazz
136 + "' and property path '"
137 + propertyName
138 + "'");
139 }
140
141 PropertyEditor editor = findCustomEditor(clazz, propertyName);
142 if (editor == null) {
143 if (LOG.isDebugEnabled()) {
144 LOG.debug("No custom property editor found using class '"
145 + clazz
146 + "' and property path '"
147 + propertyName
148 + "'. Attempting to find default property editor class.");
149 }
150 editor = getDefaultEditor(clazz);
151 }
152
153 return editor;
154 }
155
156 @Override
157 public Class<?> getPropertyType(String propertyName) throws BeansException {
158 try {
159 PropertyDescriptor pd = getPropertyDescriptorInternal(propertyName);
160 if (pd != null) {
161 return pd.getPropertyType();
162 }
163
164
165 Object value = super.getPropertyValue(propertyName);
166 if (value != null) {
167 return value.getClass();
168 }
169
170
171
172 Class<?> editorType = guessPropertyTypeFromEditors(propertyName);
173 if (editorType != null) {
174 return editorType;
175 }
176 } catch (InvalidPropertyException ex) {
177
178 }
179
180 return null;
181 }
182
183 @Override
184 protected BeanWrapperImpl getBeanWrapperForPropertyPath(String propertyPath) {
185 BeanWrapperImpl beanWrapper = super.getBeanWrapperForPropertyPath(propertyPath);
186
187 PropertyTokenHolder tokens = getPropertyNameTokens(propertyPath);
188 String canonicalName = tokens.canonicalName;
189
190 int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(canonicalName);
191 if (pos != -1) {
192 canonicalName = canonicalName.substring(0, pos);
193 }
194
195 copyCustomEditorsTo(beanWrapper, canonicalName);
196
197 return beanWrapper;
198 }
199
200 @Override
201 public Object getPropertyValue(String propertyName) throws BeansException {
202 registerEditorFromView(propertyName);
203 return super.getPropertyValue(propertyName);
204 }
205
206 @Override
207 public void setPropertyValue(PropertyValue pv) throws BeansException {
208 registerEditorFromView(pv.getName());
209 super.setPropertyValue(pv);
210 }
211
212 @Override
213 public void setPropertyValue(String propertyName, Object value) throws BeansException {
214 registerEditorFromView(propertyName);
215 super.setPropertyValue(propertyName, value);
216 }
217
218 @Override
219 public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
220
221 model = (ViewModel) object;
222 super.setWrappedInstance(object, nestedPath, rootObject);
223 }
224
225 @Override
226 public void setWrappedInstance(Object object) {
227
228 model = (ViewModel) object;
229 super.setWrappedInstance(object);
230 }
231
232
233
234
235
236
237
238 private PropertyTokenHolder getPropertyNameTokens(String propertyName) {
239 PropertyTokenHolder tokens = new PropertyTokenHolder();
240 String actualName = null;
241 List<String> keys = new ArrayList<String>(2);
242 int searchIndex = 0;
243 while (searchIndex != -1) {
244 int keyStart = propertyName.indexOf(PROPERTY_KEY_PREFIX, searchIndex);
245 searchIndex = -1;
246 if (keyStart != -1) {
247 int keyEnd = propertyName.indexOf(PROPERTY_KEY_SUFFIX, keyStart + PROPERTY_KEY_PREFIX.length());
248 if (keyEnd != -1) {
249 if (actualName == null) {
250 actualName = propertyName.substring(0, keyStart);
251 }
252 String key = propertyName.substring(keyStart + PROPERTY_KEY_PREFIX.length(), keyEnd);
253 if ((key.startsWith("'") && key.endsWith("'")) || (key.startsWith("\"") && key.endsWith("\""))) {
254 key = key.substring(1, key.length() - 1);
255 }
256 keys.add(key);
257 searchIndex = keyEnd + PROPERTY_KEY_SUFFIX.length();
258 }
259 }
260 }
261 tokens.actualName = (actualName != null ? actualName : propertyName);
262 tokens.canonicalName = tokens.actualName;
263 if (!keys.isEmpty()) {
264 tokens.canonicalName += PROPERTY_KEY_PREFIX +
265 StringUtils.collectionToDelimitedString(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX) +
266 PROPERTY_KEY_SUFFIX;
267 tokens.keys = StringUtils.toStringArray(keys);
268 }
269 return tokens;
270 }
271
272 private static class PropertyTokenHolder {
273
274 public String canonicalName;
275
276 public String actualName;
277
278 public String[] keys;
279 }
280 }