001
014
015 package com.liferay.portal.json.jabsorb.serializer;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019
020 import java.io.Serializable;
021
022 import java.lang.reflect.Constructor;
023 import java.lang.reflect.Field;
024 import java.lang.reflect.Modifier;
025
026 import java.util.HashSet;
027 import java.util.Iterator;
028 import java.util.Set;
029
030 import org.jabsorb.JSONSerializer;
031 import org.jabsorb.serializer.AbstractSerializer;
032 import org.jabsorb.serializer.MarshallException;
033 import org.jabsorb.serializer.ObjectMatch;
034 import org.jabsorb.serializer.SerializerState;
035 import org.jabsorb.serializer.UnmarshallException;
036
037 import org.json.JSONObject;
038
039
042 public class LiferaySerializer extends AbstractSerializer {
043
044 @Override
045 public boolean canSerialize(
046 @SuppressWarnings("rawtypes") Class clazz,
047 @SuppressWarnings("rawtypes") Class jsonClass) {
048
049 Constructor<?> constructor = null;
050
051 try {
052 constructor = clazz.getConstructor();
053 }
054 catch (Exception e) {
055 }
056
057 if (Serializable.class.isAssignableFrom(clazz) &&
058 ((jsonClass == null) || (jsonClass == JSONObject.class)) &&
059 (constructor != null)) {
060
061 return true;
062 }
063
064 return false;
065 }
066
067 @Override
068 public Class<?>[] getJSONClasses() {
069 return _JSON_CLASSES;
070 }
071
072 @Override
073 public Class<?>[] getSerializableClasses() {
074 return _SERIALIZABLE_CLASSES;
075 }
076
077 @Override
078 public Object marshall(
079 SerializerState serializerState, Object parentObject, Object object)
080 throws MarshallException {
081
082 JSONObject jsonObject = new JSONObject();
083
084 Class<?> javaClass = object.getClass();
085
086 if (ser.getMarshallClassHints()) {
087 try {
088 jsonObject.put("javaClass", javaClass.getName());
089 }
090 catch (Exception e) {
091 throw new MarshallException("Unable to put javaClass", e);
092 }
093 }
094
095 JSONObject serializableJSONObject = new JSONObject();
096
097 try {
098 jsonObject.put("serializable", serializableJSONObject);
099
100 serializerState.push(
101 object, serializableJSONObject, "serializable");
102 }
103 catch (Exception e) {
104 throw new MarshallException("Unable to put serializable", e);
105 }
106
107 String fieldName = null;
108
109 try {
110 Set<String> processedFieldNames = new HashSet<String>();
111
112 while (javaClass != null) {
113 Field[] declaredFields = javaClass.getDeclaredFields();
114
115 for (Field field : declaredFields) {
116 fieldName = field.getName();
117
118
119
120 if (processedFieldNames.contains(fieldName)) {
121 continue;
122 }
123
124 processedFieldNames.add(fieldName);
125
126 int modifiers = field.getModifiers();
127
128
129
130
131 if (((modifiers & Modifier.FINAL) == Modifier.FINAL) ||
132 ((modifiers & Modifier.STATIC) == Modifier.STATIC) ||
133 ((modifiers & Modifier.TRANSIENT) ==
134 Modifier.TRANSIENT)) {
135
136 continue;
137 }
138
139 if (!field.isAccessible()) {
140 field.setAccessible(true);
141 }
142
143 if (fieldName.startsWith("_")) {
144 fieldName = fieldName.substring(1);
145 }
146
147 Object fieldObject = ser.marshall(
148 serializerState, serializableJSONObject,
149 field.get(object), fieldName);
150
151
152
153
154 if (JSONSerializer.CIRC_REF_OR_DUPLICATE != fieldObject) {
155 serializableJSONObject.put(fieldName, fieldObject);
156 }
157 }
158
159 javaClass = javaClass.getSuperclass();
160 }
161 }
162 catch (Exception e) {
163 throw new MarshallException(
164 "Unable to match field " + fieldName, e);
165 }
166 finally {
167 serializerState.pop();
168 }
169
170 return jsonObject;
171 }
172
173 @Override
174 public ObjectMatch tryUnmarshall(
175 SerializerState serializerState,
176 @SuppressWarnings("rawtypes") Class clazz, Object object)
177 throws UnmarshallException {
178
179 JSONObject jsonObject = (JSONObject)object;
180
181 String javaClassName = null;
182
183 try {
184 javaClassName = jsonObject.getString("javaClass");
185 }
186 catch (Exception e) {
187 throw new UnmarshallException("Unable to get javaClass", e);
188 }
189
190 if (javaClassName == null) {
191 throw new UnmarshallException("javaClass is undefined");
192 }
193
194 try {
195 Class<?> javaClass = Class.forName(javaClassName);
196
197 Serializable.class.isAssignableFrom(javaClass);
198 }
199 catch (Exception e) {
200 throw new UnmarshallException(
201 "Unable to load javaClass " + javaClassName, e);
202 }
203
204 JSONObject serializableJSONObject = null;
205
206 try {
207 serializableJSONObject = jsonObject.getJSONObject("serializable");
208 }
209 catch (Exception e) {
210 throw new UnmarshallException("Unable to get serializable", e);
211 }
212
213 if (serializableJSONObject == null) {
214 throw new UnmarshallException("serializable is undefined");
215 }
216
217 ObjectMatch objectMatch = new ObjectMatch(-1);
218
219 serializerState.setSerialized(object, objectMatch);
220
221 String fieldName = null;
222
223 try {
224 Iterator<?> iterator = serializableJSONObject.keys();
225
226 while (iterator.hasNext()) {
227 fieldName = (String)iterator.next();
228
229 ObjectMatch fieldObjectMatch = ser.tryUnmarshall(
230 serializerState, null,
231 serializableJSONObject.get(fieldName));
232
233 ObjectMatch maxFieldObjectMatch = fieldObjectMatch.max(
234 objectMatch);
235
236 objectMatch.setMismatch(maxFieldObjectMatch.getMismatch());
237 }
238 }
239 catch (Exception e) {
240 throw new UnmarshallException(
241 "Unable to match field " + fieldName, e);
242 }
243
244 return objectMatch;
245 }
246
247 @Override
248 public Object unmarshall(
249 SerializerState serializerState,
250 @SuppressWarnings("rawtypes") Class clazz, Object object)
251 throws UnmarshallException {
252
253 JSONObject jsonObject = (JSONObject)object;
254
255 String javaClassName = null;
256
257 try {
258 javaClassName = jsonObject.getString("javaClass");
259 }
260 catch (Exception e) {
261 throw new UnmarshallException("Unable to get javaClass", e);
262 }
263
264 if (javaClassName == null) {
265 throw new UnmarshallException("javaClass is undefined");
266 }
267
268 Class<?> javaClass = null;
269
270 Object javaClassInstance = null;
271
272 try {
273 javaClass = Class.forName(javaClassName);
274
275 javaClassInstance = javaClass.newInstance();
276 }
277 catch (Exception e) {
278 throw new UnmarshallException(
279 "Unable to load javaClass " + javaClassName, e);
280 }
281
282 JSONObject serializableJSONObject = null;
283
284 try {
285 serializableJSONObject = jsonObject.getJSONObject("serializable");
286 }
287 catch (Exception e) {
288 throw new UnmarshallException("Unable to get serializable", e);
289 }
290
291 if (serializableJSONObject == null) {
292 throw new UnmarshallException("serializable is undefined");
293 }
294
295 serializerState.setSerialized(object, javaClassInstance);
296
297 String fieldName = null;
298
299 try {
300 Set<String> processedFieldNames = new HashSet<String>();
301
302 while (javaClass != null) {
303 Field[] fields = javaClass.getDeclaredFields();
304
305 for (Field field : fields) {
306 fieldName = field.getName();
307
308
309
310 if (processedFieldNames.contains(fieldName)) {
311 continue;
312 }
313
314 processedFieldNames.add(fieldName);
315
316 int modifiers = field.getModifiers();
317
318
319
320
321 if (((modifiers & Modifier.FINAL) == Modifier.FINAL) ||
322 ((modifiers & Modifier.STATIC) == Modifier.STATIC) ||
323 ((modifiers & Modifier.TRANSIENT) ==
324 Modifier.TRANSIENT)) {
325
326 continue;
327 }
328
329 if (!field.isAccessible()) {
330 field.setAccessible(true);
331 }
332
333 if (fieldName.startsWith("_")) {
334 fieldName = fieldName.substring(1);
335 }
336
337 Object value = null;
338
339 try {
340 value = ser.unmarshall(
341 serializerState, field.getType(),
342 serializableJSONObject.get(fieldName));
343 }
344 catch (Exception e) {
345 }
346
347 if (value != null) {
348 try {
349 field.set(javaClassInstance, value);
350 }
351 catch (Exception e) {
352 _log.error(e, e);
353 }
354 }
355 }
356
357 javaClass = javaClass.getSuperclass();
358 }
359 }
360 catch (Exception e) {
361 throw new UnmarshallException(
362 "Unable to match field " + fieldName, e);
363 }
364
365 return javaClassInstance;
366 }
367
368 private static final Class<?>[] _JSON_CLASSES = {JSONObject.class};
369
370 private static final Class<?>[] _SERIALIZABLE_CLASSES =
371 {Serializable.class};
372
373 private static Log _log = LogFactoryUtil.getLog(LiferaySerializer.class);
374
375 }