1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.kuali.kfs.sys.context;
20
21 import java.lang.reflect.Field;
22 import java.lang.reflect.Modifier;
23 import java.util.HashSet;
24 import java.util.Map;
25 import java.util.Set;
26
27 import org.apache.commons.lang.StringUtils;
28 import org.kuali.kfs.sys.ConfigureContext;
29 import org.kuali.rice.krad.datadictionary.DataDictionary;
30 import org.kuali.rice.krad.datadictionary.DocumentEntry;
31 import org.kuali.rice.krad.service.DataDictionaryService;
32
33 @ConfigureContext
34
35
36
37 public class DocumentSerializabilityTest extends KualiTestBase {
38 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentSerializabilityTest.class);
39
40
41
42 public void testAllDocumentsAreSerializable() {
43 DataDictionary dataDictionary = SpringContext.getBean(DataDictionaryService.class).getDataDictionary();
44 Map<String, DocumentEntry> documentEntries = dataDictionary.getDocumentEntries();
45 Set<Class<?>> checkedClasses = new HashSet<Class<?>>();
46 Set<Class<?>> unserializableClasses = new HashSet<Class<?>>();
47 String errorMessage = "";
48
49 for (String documentEntryName : documentEntries.keySet()) {
50 if (LOG.isDebugEnabled()) {
51 LOG.debug("Checking: "+documentEntryName);
52 }
53 DocumentEntry entry = documentEntries.get(documentEntryName);
54
55 Set<String> unserializableFields = null;
56 Class<?> testedClass;
57 if (entry instanceof org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry) {
58 testedClass = ((org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry)entry).getMaintainableClass();
59 if ( testedClass == null ) {
60 errorMessage += "Maintenance Document entry: " + documentEntryName + " has a null maintainable class";
61 } else {
62 unserializableFields = getUnserializableFieldsFromClass(testedClass);
63 }
64 } else if (entry instanceof org.kuali.rice.kns.datadictionary.TransactionalDocumentEntry) {
65 testedClass = ((org.kuali.rice.kns.datadictionary.TransactionalDocumentEntry)entry).getDocumentClass();
66 if ( testedClass == null ) {
67 errorMessage += "Transactional Document entry: " + documentEntryName + " has a null document class";
68 } else {
69 unserializableFields = getUnserializableFieldsFromClass(testedClass);
70 }
71 } else {
72 unserializableFields = null;
73 testedClass = null;
74 }
75
76 if (testedClass != null && !checkedClasses.contains(testedClass)) {
77 checkedClasses.add(testedClass);
78 if (unserializableFields != null && !unserializableFields.isEmpty()) {
79 errorMessage += "Class "+testedClass.getName()+" has unserializable fields: "+StringUtils.join(unserializableFields, ',')+"\n";
80 unserializableClasses.add(testedClass);
81 }
82 }
83 }
84
85 if (!StringUtils.isBlank(errorMessage)) {
86 LOG.info(errorMessage);
87 }
88 assertTrue(errorMessage, StringUtils.isEmpty(errorMessage) );
89 }
90
91
92
93
94
95
96 protected Set<String> getUnserializableFieldsFromClass(Class<?> clazz) {
97 Set<String> unserializableFields = new HashSet<String>();
98
99 if (clazz.getSuperclass() != null && !clazz.equals(java.lang.Object.class)) {
100 unserializableFields.addAll(getUnserializableFieldsFromClass(clazz.getSuperclass()));
101 }
102 Field[] fields = clazz.getDeclaredFields();
103 for (Field field : fields) {
104 if (!isSerializable(field)) {
105 unserializableFields.add(field.getName());
106 }
107 }
108
109 return unserializableFields;
110 }
111
112
113
114
115
116
117 protected boolean isSerializable(Field field) {
118 return java.io.Serializable.class.isAssignableFrom(field.getType())
119 || java.util.Collection.class.isAssignableFrom(field.getType())
120 || java.util.Map.class.isAssignableFrom(field.getType())
121 || field.getName().equals("dataObject")
122 || Modifier.isTransient(field.getModifiers())
123 || Modifier.isStatic(field.getModifiers())
124 || isPrimitive(field.getType());
125 }
126
127
128
129
130
131
132 protected boolean isPrimitive(Class<?> clazz) {
133 return Byte.TYPE.isAssignableFrom(clazz) || Short.TYPE.isAssignableFrom(clazz) || Integer.TYPE.isAssignableFrom(clazz) || Long.TYPE.isAssignableFrom(clazz) || Float.TYPE.isAssignableFrom(clazz) || Double.TYPE.isAssignableFrom(clazz) || Character.TYPE.isAssignableFrom(clazz) || Boolean.TYPE.isAssignableFrom(clazz);
134 }
135 }