1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.util;
17
18 import java.util.List;
19 import java.util.Map;
20 import java.util.concurrent.ConcurrentHashMap;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.commons.lang.Validate;
24 import org.kuali.rice.core.api.config.property.ConfigContext;
25 import org.kuali.rice.core.framework.util.ReflectionUtils;
26 import org.kuali.rice.krad.data.metadata.MetadataRepository;
27 import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
28 import org.kuali.rice.krad.service.DataDictionaryService;
29 import org.springframework.util.ClassUtils;
30
31 import com.google.common.collect.Lists;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 class LegacyDetector {
66 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LegacyDetector.class);
67
68
69
70 private static final String OJB_METADATA_MANAGER_CLASS = "org.apache.ojb.broker.metadata.MetadataManager";
71
72 private final MetadataRepository metadataRepository;
73 private final DataDictionaryService dataDictionaryService;
74
75 private final Map<Class<?>, Boolean> legacyLoadedCache = new ConcurrentHashMap<Class<?>, Boolean>();
76
77 private static ThreadLocal<Integer> legacyContext = new ThreadLocal<Integer>();
78
79 LegacyDetector(MetadataRepository metadataRepository, DataDictionaryService dataDictionaryService) {
80 Validate.notNull(metadataRepository, "The metadataRepository must not be null");
81 Validate.notNull(dataDictionaryService, "The dataDictionaryService must not be null");
82 this.metadataRepository = metadataRepository;
83 this.dataDictionaryService = dataDictionaryService;
84 }
85
86 public boolean isInLegacyContext() {
87 return legacyContext.get() != null;
88 }
89
90 public void beginLegacyContext() {
91 Integer count = legacyContext.get();
92 if (count == null) {
93
94 if (!isLegacyDataFrameworkEnabled()) {
95 throw new IllegalStateException(
96 "Attempting to enter legacy data context without the legacy data framework enabled."
97 + " To enable, please load the KNS module or set "
98 + KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK
99 + " config property to 'true'.");
100 }
101 legacyContext.set(new Integer(0));
102 } else {
103 legacyContext.set(new Integer(count.intValue() + 1));
104 }
105 }
106
107 public void endLegacyContext() {
108 Integer count = legacyContext.get();
109 if (count == null) {
110 throw new IllegalStateException("Attempting to end a non-existent legacy context!");
111 } else if (count.intValue() == 0) {
112 legacyContext.set(null);
113 } else {
114 legacyContext.set(new Integer(count.intValue() - 1));
115 }
116 }
117
118 public boolean isLegacyManaged(Class<?> type) {
119 BusinessObjectEntry businessObjectEntry =
120 dataDictionaryService.getDataDictionary().getBusinessObjectEntry(type.getName());
121 return businessObjectEntry != null || isOjbLoadedClass(type);
122 }
123
124
125
126
127
128
129 public boolean isKradDataManaged(Class<?> type) {
130 return metadataRepository.contains(type);
131 }
132
133
134
135
136
137
138
139 public boolean isKnsEnabled() {
140 return ConfigContext.getCurrentContextConfig().getBooleanProperty(KRADConstants.Config.KNS_ENABLED, false);
141 }
142
143
144
145
146
147
148 public boolean isLegacyDataFrameworkEnabled() {
149 return ConfigContext.getCurrentContextConfig().getBooleanProperty(KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK, isKnsEnabled());
150 }
151
152
153
154
155
156
157
158
159 public boolean isOjbLoadedClass(Class<?> dataObjectClass) {
160 if (dataObjectClass == null) {
161 return false;
162 }
163
164
165 String dataObjectClassName = dataObjectClass.getName().replaceAll("\\$\\$EnhancerByCGLIB\\$\\$[0-9a-f]{0,8}", "" );
166 try {
167 dataObjectClass = Class.forName(dataObjectClassName);
168 } catch (ClassNotFoundException ex) {
169 LOG.warn( "Unable to resolve converted class name: " + dataObjectClassName + " from original: " + dataObjectClass + " -- Using as is" );
170 }
171 Boolean isLegacyLoaded = legacyLoadedCache.get(dataObjectClass);
172 if (isLegacyLoaded == null) {
173 if ( dataObjectClass.getPackage() != null
174 && StringUtils.startsWith( dataObjectClass.getPackage().getName(), "org.apache.ojb." ) ) {
175 isLegacyLoaded = Boolean.TRUE;
176 } else {
177 try {
178 Class<?> metadataManager = Class.forName(OJB_METADATA_MANAGER_CLASS, false, ClassUtils.getDefaultClassLoader());
179
180
181 Object metadataManagerInstance = ReflectionUtils.invokeViaReflection(metadataManager, (Object) null, "getInstance", null);
182 Validate.notNull(metadataManagerInstance , "unable to obtain " + OJB_METADATA_MANAGER_CLASS + " instance");
183
184 Object descriptorRepository = ReflectionUtils.invokeViaReflection(metadataManagerInstance, "getGlobalRepository", null);
185 Validate.notNull(descriptorRepository, "unable to invoke legacy metadata provider (" + OJB_METADATA_MANAGER_CLASS + ")");
186
187 isLegacyLoaded = ReflectionUtils.invokeViaReflection(descriptorRepository, "hasDescriptorFor", new Class[] { Class.class }, dataObjectClass);
188
189 } catch (ClassNotFoundException e) {
190
191 isLegacyLoaded = Boolean.FALSE;
192 }
193 }
194 legacyLoadedCache.put(dataObjectClass, isLegacyLoaded);
195 }
196 return isLegacyLoaded.booleanValue();
197 }
198
199
200
201
202
203
204 public boolean useLegacy(Class<?> dataObjectClass) {
205
206
207 boolean ojbLoadedClass = isOjbLoadedClass(dataObjectClass);
208 if (isInLegacyContext() && ojbLoadedClass) {
209 return true;
210 }
211
212
213
214 if (isLegacyDataFrameworkEnabled() &&
215 (ojbLoadedClass || isTransientBO(dataObjectClass)) &&
216 !isKradDataManaged(dataObjectClass)) {
217 return true;
218 }
219
220 return false;
221 }
222
223
224
225
226
227
228
229
230 private boolean isTransientBO(Class dataObjectClass) {
231 boolean isTransientBo = false;
232
233 List<String> transientClassNames = Lists.newArrayList(
234 "org.kuali.rice.krad.bo.TransientBusinessObjectBase");
235
236 try {
237 Object dataObject = dataObjectClass.newInstance();
238
239 for (String transientClassName : transientClassNames) {
240 Class<?> transientClass = Class.forName(transientClassName);
241
242 if (transientClass.isInstance(dataObject)) {
243 isTransientBo = true;
244 break;
245 }
246 }
247 } catch (Exception e) {
248 return false;
249 }
250
251 return isTransientBo;
252 }
253
254
255
256
257
258
259 public boolean useLegacyForObject(Object dataObject) {
260 Validate.notNull(dataObject, "Data Object must not be null");
261 if (dataObject instanceof Class) {
262 throw new IllegalArgumentException("Passed a Class object to useLegacyForObject, call useLegacy instead!");
263 }
264 return useLegacy(dataObject.getClass());
265 }
266 }