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