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