001
014
015 package com.liferay.portal.json;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.util.StringPool;
020 import com.liferay.portal.util.PropsValues;
021
022 import flexjson.BeanAnalyzer;
023 import flexjson.BeanProperty;
024 import flexjson.JSONException;
025 import flexjson.ObjectBinder;
026
027 import flexjson.factories.BeanObjectFactory;
028
029 import java.lang.reflect.Field;
030 import java.lang.reflect.Modifier;
031 import java.lang.reflect.Type;
032
033 import java.util.HashMap;
034 import java.util.Map;
035 import java.util.concurrent.ConcurrentHashMap;
036
037
040 public class PortalBeanObjectFactory extends BeanObjectFactory {
041
042 @Override
043 public Object instantiate(
044 ObjectBinder objectBinder, Object value, Type targetType,
045 @SuppressWarnings("rawtypes") Class targetClass) {
046
047 if (_safeMode) {
048 Map<Object, Object> target = new HashMap<Object, Object>();
049
050 target.put("class", targetClass.getName());
051
052 Map<?, ?> values = (Map<?, ?>)value;
053
054 return objectBinder.bindIntoMap(values, target, null, null);
055 }
056
057 String targetClassName = targetClass.getName();
058
059 if (targetClassName.contains("com.liferay") &&
060 targetClassName.contains("Util")) {
061
062 throw new JSONException(
063 "Not instantiating " + targetClass.getName() + " at " +
064 objectBinder.getCurrentPath());
065 }
066
067 try {
068 Object target = instantiate(targetClass);
069
070 Map<?, ?> values = (Map<?, ?>)value;
071
072 if (PropsValues.JSON_DESERIALIZER_STRICT_MODE) {
073 removeInvalidFields(values, targetClass);
074 }
075
076 return objectBinder.bindIntoObject(values, target, targetType);
077 }
078 catch (Exception e) {
079 throw new JSONException(
080 "Unable to instantiate " + targetClass.getName() + " at " +
081 objectBinder.getCurrentPath(),
082 e);
083 }
084 }
085
086 public void setSafeMode(boolean safeMode) {
087 _safeMode = safeMode;
088 }
089
090 protected Map<String, Field> getDeclaredFields(
091 @SuppressWarnings("rawtypes") Class targetClass) {
092
093 Map<String, Field> declaredFieldsMap = _declaredFields.get(targetClass);
094
095 if (declaredFieldsMap == null) {
096 declaredFieldsMap = new ConcurrentHashMap<String, Field>();
097
098 Field[] declaredFields = targetClass.getDeclaredFields();
099
100 for (Field declaredField : declaredFields) {
101 String fieldName = declaredField.getName();
102
103 if (fieldName.startsWith(StringPool.UNDERLINE)) {
104 fieldName = fieldName.substring(1);
105 }
106
107 declaredFieldsMap.put(fieldName, declaredField);
108 }
109
110 _declaredFields.put(targetClass, declaredFieldsMap);
111 }
112
113 return declaredFieldsMap;
114 }
115
116 protected boolean isValidField(
117 Map<String, Field> declaredFields, String beanName) {
118
119 Field declaredField = declaredFields.get(beanName);
120
121 if (declaredField == null) {
122 return false;
123 }
124
125 int modifier = declaredField.getModifiers();
126
127 if (Modifier.isStatic(modifier)) {
128 return false;
129 }
130
131 return true;
132 }
133
134 protected void removeInvalidFields(Map<?, ?> values, Class<?> targetClass) {
135 Map<String, Field> declaredFields = getDeclaredFields(targetClass);
136
137 BeanAnalyzer beanAnalyzer = BeanAnalyzer.analyze(targetClass);
138
139 for (BeanProperty beanProperty : beanAnalyzer.getProperties()) {
140 String beanName = beanProperty.getName();
141
142 String capitalizedBeanName = null;
143
144 Object beanValue = values.get(beanName);
145
146 if (beanValue == null) {
147 capitalizedBeanName = Character.toUpperCase(
148 beanName.charAt(0)) + beanName.substring(1);
149
150 beanValue = values.get(capitalizedBeanName);
151 }
152
153 if ((beanValue != null) &&
154 !isValidField(declaredFields, beanName)) {
155
156 if (capitalizedBeanName != null) {
157 beanName = capitalizedBeanName;
158 }
159
160 if (_log.isDebugEnabled()) {
161 _log.debug("Removing non-JavaBeans field " + beanName);
162 }
163
164 values.remove(beanName);
165 }
166 }
167 }
168
169 private static Log _log = LogFactoryUtil.getLog(
170 PortalBeanObjectFactory.class);
171
172 private Map<Class<?>, Map<String, Field>> _declaredFields =
173 new ConcurrentHashMap<Class<?>, Map<String, Field>>();
174 private boolean _safeMode;
175
176 }