View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.util;
17  
18  import org.apache.ojb.broker.metadata.ClassDescriptor;
19  import org.apache.ojb.broker.metadata.DescriptorRepository;
20  import org.apache.ojb.broker.metadata.MetadataManager;
21  import org.junit.After;
22  import org.junit.Before;
23  import org.junit.Test;
24  import org.junit.runner.RunWith;
25  import org.kuali.rice.core.api.config.property.ConfigContext;
26  import org.kuali.rice.core.api.util.ContextClassLoaderBinder;
27  import org.kuali.rice.core.framework.config.property.SimpleConfig;
28  import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
29  import org.kuali.rice.krad.data.metadata.MetadataRepository;
30  import org.kuali.rice.krad.datadictionary.DataDictionary;
31  import org.kuali.rice.krad.service.DataDictionaryService;
32  import org.mockito.Mock;
33  import org.mockito.invocation.InvocationOnMock;
34  import org.mockito.runners.MockitoJUnitRunner;
35  import org.mockito.stubbing.Answer;
36  
37  import java.lang.reflect.Field;
38  import java.util.HashSet;
39  import java.util.Set;
40  import java.util.concurrent.Callable;
41  
42  import static org.junit.Assert.*;
43  import static org.mockito.Mockito.*;
44  
45  /**
46   * Tests LegacyDetectionService
47   */
48  @RunWith(MockitoJUnitRunner.class)
49  public class LegacyDetectorTest {
50  
51      private static class DummyDataObject {}
52      private static class DummyDataObjectOjb {}
53  
54      private Set<Class<?>> nonLegacyClasses = new HashSet<Class<?>>();
55  
56      @Mock private MetadataManager metadataManager;
57      @Mock private MetadataRepository metadataRepository;
58      @Mock private DataDictionaryService dataDictionaryService;
59      @Mock private DataDictionary dataDictionary;
60  
61      private MetadataManager existingMetadataManager = null;
62  
63      private LegacyDetector detector;
64  
65      @Before
66      public void setUp() throws Exception {
67  
68          DescriptorRepository descriptorRepository = new DescriptorRepository();
69          when(metadataManager.getGlobalRepository()).thenReturn(descriptorRepository);
70          this.existingMetadataManager = hackOjb(metadataManager);
71  
72          when(metadataRepository.contains(any(Class.class))).thenAnswer(new Answer() {
73              @Override
74              public Object answer(InvocationOnMock invocation) {
75                  Class<?> type = (Class<?>)invocation.getArguments()[0];
76                  return nonLegacyClasses.contains(type);
77              }
78          });
79  
80          when(dataDictionaryService.getDataDictionary()).thenReturn(dataDictionary);
81  
82          nonLegacyClasses.clear();
83  
84          ConfigContext.init(new SimpleConfig());
85          ConfigContext.getCurrentContextConfig().removeProperty(KRADConstants.Config.KNS_ENABLED);
86          ConfigContext.getCurrentContextConfig().removeProperty(KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK);
87  
88          this.detector = new LegacyDetector(this.metadataRepository, this.dataDictionaryService);
89  
90          addOjbClass(DummyDataObjectOjb.class);
91      }
92  
93      @After
94      public void tearDown() throws Exception {
95          unhackOjb(this.existingMetadataManager);
96      }
97  
98      @Test
99      public void testKnsDisabledByDefault() {
100         assertFalse(detector.isKnsEnabled());
101     }
102 
103     @Test
104     public void testKnsEnabledByConfig() {
105         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.KNS_ENABLED, "true");
106         assertTrue(detector.isKnsEnabled());
107     }
108 
109     @Test
110     public void testKnsDisabledByConfig() {
111         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.KNS_ENABLED, "false");
112         assertFalse(detector.isKnsEnabled());
113     }
114 
115     @Test
116     public void testLegacyDataFrameworkDisabledByDefault() {
117         assertFalse(detector.isLegacyDataFrameworkEnabled());
118     }
119 
120     @Test
121     public void testLegacyDataFrameworkEnabledByKnsByDefault() {
122         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.KNS_ENABLED, "true");
123         assertTrue(detector.isLegacyDataFrameworkEnabled());
124     }
125 
126     @Test
127     public void testLegacyDataFrameworkDisabledByKnsByDefault() {
128         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.KNS_ENABLED, "false");
129         assertFalse(detector.isLegacyDataFrameworkEnabled());
130     }
131 
132     @Test
133     public void testLegacyDataFrameworkEnabledByConfig() {
134         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.KNS_ENABLED, "false");
135         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK, "true");
136         assertTrue(detector.isLegacyDataFrameworkEnabled());
137     }
138 
139     @Test
140     public void testLegacyDataFrameworkDisabledByConfig() {
141         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.KNS_ENABLED, "true");
142         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK, "false");
143         assertFalse(detector.isLegacyDataFrameworkEnabled());
144     }
145 
146     @Test
147     public void testDataObjectNotLegacyWhenDisabled() {
148         addOjbClass(DummyDataObject.class);
149         assertFalse(detector.isLegacyDataFrameworkEnabled());
150         assertFalse(detector.useLegacyForObject(new DummyDataObject()));
151         assertFalse(detector.useLegacy(DummyDataObject.class));
152     }
153 
154     @Test
155     public void testDataObjectNotLegacyWhenNotLoaded() {
156         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK, "true");
157         assertTrue(detector.isLegacyDataFrameworkEnabled());
158         assertFalse(detector.useLegacyForObject(new DummyDataObject()));
159         assertFalse(detector.useLegacy(DummyDataObject.class));
160     }
161 
162     @Test
163     public void testDataObjectIsLegacyWhenEnabledAndLoaded() {
164         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK, "true");
165         addOjbClass(DummyDataObject.class);
166         assertTrue(detector.isLegacyDataFrameworkEnabled());
167         assertTrue(detector.useLegacyForObject(new DummyDataObject()));
168         assertTrue(detector.useLegacy(DummyDataObject.class));
169     }
170 
171     @Test
172     public void testUseLegacy_InContext() {
173         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK, "true");
174         detector.beginLegacyContext();
175         try {
176             // since recent changes, if it's not in OJB, it's not legacy
177             assertFalse(detector.useLegacy(DummyDataObject.class));
178             assertTrue(detector.useLegacy(DummyDataObjectOjb.class));
179         } finally {
180             detector.endLegacyContext();
181         }
182     }
183 
184     @Test(expected = IllegalStateException.class)
185     public void testUseLegacy_LegacyFrameworkDisabled() {
186         detector.beginLegacyContext();
187         try {
188             detector.useLegacy(DummyDataObject.class);
189         } finally {
190             detector.endLegacyContext();
191         }
192     }
193 
194     /**
195      * Verifies that if you pass an instance of java.lang.Class to useLegacyForObject, that it
196      * throws an IllegalArgumentException since you should use the useLegacy method for that
197      */
198     @Test(expected = IllegalArgumentException.class)
199     public void testUseLegacyForObject_PassingAClassIsBad() {
200         detector.useLegacyForObject(DummyDataObject.class);
201     }
202 
203     @Test(expected=IllegalStateException.class)
204     public void testBeginLegacyContext_LegacyFrameworkDisabled() {
205         detector.beginLegacyContext();
206     }
207 
208     @Test(expected=IllegalStateException.class)
209     public void testEndLegacyContext_NoContext() {
210         detector.endLegacyContext();
211     }
212 
213     @Test
214     public void testBeginEndLegacyContext() {
215         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK, "true");
216         assertFalse(detector.isInLegacyContext());
217         detector.beginLegacyContext();
218         try {
219             assertTrue(detector.isInLegacyContext());
220         } finally {
221             detector.endLegacyContext();
222         }
223         assertFalse(detector.isInLegacyContext());
224     }
225 
226     @Test
227     public void testNestedLegacyContext() {
228         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK, "true");
229         assertFalse(detector.isInLegacyContext());
230         detector.beginLegacyContext();
231         try {
232             assertTrue(detector.isInLegacyContext());
233             detector.beginLegacyContext();
234             try {
235                 detector.beginLegacyContext();
236                 try {
237                     assertTrue(detector.isInLegacyContext());
238                 } finally {
239                     detector.endLegacyContext();
240                 }
241                 assertTrue(detector.isInLegacyContext());
242             } finally {
243                 detector.endLegacyContext();
244             }
245             assertTrue(detector.isInLegacyContext());
246         } finally {
247             detector.endLegacyContext();
248         }
249         assertFalse(detector.isInLegacyContext());
250     }
251 
252     @Test
253     public void testIllegallyNestedLegacyContext() {
254         ConfigContext.getCurrentContextConfig().putProperty(KRADConstants.Config.ENABLE_LEGACY_DATA_FRAMEWORK, "true");
255         assertFalse(detector.isInLegacyContext());
256         detector.beginLegacyContext();
257         assertTrue(detector.isInLegacyContext());
258         detector.endLegacyContext();
259         assertFalse(detector.isInLegacyContext());
260         try {
261             detector.endLegacyContext();
262             fail("Should have thrown IllegalStateException");
263         } catch (IllegalStateException e) {
264             // this should happen!
265         }
266     }
267 
268     @Test
269     public void testIsOjbLoadedClass() {
270         assertFalse(detector.isOjbLoadedClass(DummyDataObject.class));
271         assertTrue(detector.isOjbLoadedClass(DummyDataObjectOjb.class));
272     }
273 
274     /**
275      * Verifies that isLegacyManaged reports that the object is legacy managed if it has a BusinessObjectEntry and
276      * nothing else.
277      */
278     @Test
279     public void testIsLegacyManaged_withBusinessObjectEntry() {
280         assertFalse(detector.isLegacyManaged(DummyDataObject.class));
281         when(dataDictionary.getBusinessObjectEntry(DummyDataObject.class.getName())).thenReturn(
282                 new BusinessObjectEntry());
283         assertTrue(detector.isLegacyManaged(DummyDataObject.class));
284         assertFalse(detector.isLegacyManaged(String.class));
285         verify(dataDictionary, times(2)).getBusinessObjectEntry(DummyDataObject.class.getName());
286         verify(dataDictionary, times(3)).getBusinessObjectEntry(anyString());
287     }
288 
289     /**
290      * Verifies that isLegacyManaged reports that the object is legacy managed if it is mapped in OJB.
291      */
292     @Test
293     public void testIsLegacyManaged_ojbLoaded() {
294         assertFalse(detector.isLegacyManaged(DummyDataObject.class));
295         // it must be mapped in ojb
296         assertTrue(detector.isLegacyManaged(DummyDataObjectOjb.class));
297     }
298 
299     /**
300      * Ensures false is returned form isOjbLoadedClass if OJB is not on the classpath.
301      */
302     @Test
303     public void testIsOjbLoadedClass_NoOjbOnClasspath() throws Exception {
304         // set an empty classloader to cause the check to load OJB MetadataManager to fail from inside isOjbLoadedClass
305         ContextClassLoaderBinder.doInContextClassLoader(ClassLoader.getSystemClassLoader().getParent(),
306                 new Callable<Object>() {
307                     @Override
308                     public Object call() throws Exception {
309                         assertFalse(detector.isOjbLoadedClass(DummyDataObjectOjb.class));
310                         return null;
311                     }
312                 });
313     }
314 
315     private void addOjbClass(Class<?> type) {
316         ClassDescriptor classDescriptor = new ClassDescriptor(metadataManager.getGlobalRepository());
317         classDescriptor.setClassOfObject(type);
318         metadataManager.getGlobalRepository().put(type, classDescriptor);
319     }
320 
321     /**
322      * Hacks OJB to put a stubbed MetadataManager into place.
323      */
324     private MetadataManager hackOjb(MetadataManager mockMetadataManager) throws Exception {
325         Field singletonField = MetadataManager.class.getDeclaredField("singleton");
326         singletonField.setAccessible(true);
327         MetadataManager existingMetadataManager = (MetadataManager)singletonField.get(null);
328         singletonField.set(null, mockMetadataManager);
329         return existingMetadataManager;
330     }
331 
332     private void unhackOjb(MetadataManager existingMetadataManager) throws Exception{
333         Field singletonField = MetadataManager.class.getDeclaredField("singleton");
334         singletonField.setAccessible(true);
335         singletonField.set(null, this.existingMetadataManager);
336 
337     }
338 
339 }