View Javadoc
1   /**
2    * Copyright 2005-2014 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.kew.plugin;
17  
18  import org.apache.commons.io.FileUtils;
19  import org.junit.Test;
20  import org.kuali.rice.core.api.config.CoreConfigHelper;
21  import org.kuali.rice.core.api.util.ClasspathOrFileResourceLoader;
22  import org.kuali.rice.kew.test.KEWTestCase;
23  import org.kuali.rice.kew.test.TestUtilities;
24  
25  import javax.xml.namespace.QName;
26  import java.io.File;
27  
28  import static org.junit.Assert.*;
29  
30  /**
31   * Tests the HotDeployer and Reloader which handle hot deployment and hot reloading
32   * of Plugins.
33   *
34   * @author Kuali Rice Team (rice.collab@kuali.org)
35   */
36  public class HotDeployTest extends KEWTestCase {
37  
38  	private File pluginDir;
39  	
40  	@Override
41  	public void setUp() throws Exception {
42          super.setUp();
43  		TestUtilities.initializePluginDirectories();
44  		this.pluginDir = TestUtilities.getPluginsDirectory(); 
45  	}
46  		
47  	@Override
48  	public void tearDown() throws Exception {
49  		super.tearDown();
50  		TestUtilities.cleanupPluginDirectories();
51  	}
52  
53  	@Test public void testHotDeploy() throws Exception {
54  		// Grab the ServerPluginRegistry
55  		PluginRegistry theRegistry = PluginUtils.getPluginRegistry();
56  		assertNotNull("PluginRegistry should exist.", theRegistry);
57  		assertTrue(theRegistry instanceof ServerPluginRegistry);
58  		ServerPluginRegistry registry = (ServerPluginRegistry)theRegistry; 
59  		
60  		// Let's shut down the asynchronous reloader and hot deployer because we want to do this synchronously.
61  		HotDeployer hotDeployer = registry.getHotDeployer();
62  		Reloader reloader = registry.getReloader();
63  		registry.stopHotDeployer();
64  		registry.stopReloader();
65  		
66  		// Assert that there are currently no plugins
67  		assertEquals("There should be no plugins.", 0, registry.getPluginEnvironments().size());
68  		assertEquals("Resource loader should have no children.", 0, registry.getResourceLoaders().size());
69  		
70  		// query the hot deployer directly about it's added and removed plugins
71  		assertEquals("There should be no plugins added.", 0, hotDeployer.getAddedPlugins().size());
72  		assertEquals("There should be no plugins removed.", 0, hotDeployer.getRemovedPlugins().size());
73  		hotDeployer.run();
74  		assertEquals("There should still be no plugins.", 0, registry.getPluginEnvironments().size());
75  		
76  		// now let's copy a plugin over and run the hot deployer
77          String pluginZipFileLocation = new ClasspathOrFileResourceLoader().getResource("classpath:org/kuali/rice/kew/plugin/ziptest.zip").getURL().getPath();
78  		File pluginZipFile = new File(pluginZipFileLocation);
79  		assertTrue("Plugin file '" + pluginZipFileLocation + "' should exist", pluginZipFile.exists());
80  		assertTrue("Plugin file '" + pluginZipFileLocation + "' should be a file", pluginZipFile.isFile());
81  		FileUtils.copyFileToDirectory(pluginZipFile, pluginDir);
82  			
83  		assertEquals("There should be one plugin added.", 1, hotDeployer.getAddedPlugins().size());
84  		assertEquals("There should be no plugins removed.", 0, hotDeployer.getRemovedPlugins().size());
85  			
86  		hotDeployer.run();
87  			
88  		// the plugin should have been hot deployed
89  		assertEquals("Plugin should have been hot deployed.", 1, registry.getPluginEnvironments().size());
90  		
91  		// check added plugins again, it should now indicate no new added plugins
92  		assertEquals("There should be no plugins added.", 0, hotDeployer.getAddedPlugins().size());
93  		assertEquals("There should be no plugins removed.", 0, hotDeployer.getRemovedPlugins().size());
94  		
95  		// verify that the resource loading and the registry are sane and properly set up with the new plugin
96  		assertEquals("Resource loader should have 1 plugin child.", 1, registry.getResourceLoaders().size());
97  		Plugin plugin = (Plugin)registry.getResourceLoaders().get(0);
98  		assertEquals("Plugin has wrong name.", new QName(CoreConfigHelper.getApplicationId(), "ziptest"), plugin.getName());
99  		assertTrue("Plugin should be started.", plugin.isStarted());
100 		assertEquals("Plugin in resource loader and environment should be the same.", plugin, registry.getPluginEnvironment(plugin.getName().getLocalPart()).getPlugin());
101 		
102 		// The reloader should have a reference to the environment
103 		assertEquals("Reloader should have a reference to environment.", 1, reloader.getReloadables().size());
104 		
105 		// now remove the plugin and ensure that it goes away
106 		FileUtils.forceDelete(new File(pluginDir, "ziptest.zip"));
107 		assertEquals("There should be no plugins added.", 0, hotDeployer.getAddedPlugins().size());
108 		assertEquals("There should be one plugin removed.", 1, hotDeployer.getRemovedPlugins().size());
109 		hotDeployer.run();
110 		
111 		// verify that the resource loading and the registry no longer contain the plugin
112 		assertEquals("No plugins should be deployed.", 0, registry.getPluginEnvironments().size());
113 		assertEquals("Resource loader should have 0 plugin children.", 0, registry.getResourceLoaders().size());
114 		
115 		// also assert that the reloader no longer has a reference to the environment
116 		assertEquals("Reloader should no longer have reference to environment.", 0, reloader.getReloadables().size());
117 				
118 	}
119 	
120 	@Test public void testReloader() throws Exception {
121 		// Grab the ServerPluginRegistry
122 		PluginRegistry theRegistry = PluginUtils.getPluginRegistry();
123 		assertNotNull("PluginRegistry should exist.", theRegistry);
124 		assertTrue(theRegistry instanceof ServerPluginRegistry);
125 		ServerPluginRegistry registry = (ServerPluginRegistry)theRegistry; 
126 		
127 		// Let's shut down the asynchronous reloader and hot deployer because we want to do this synchronously.
128 		HotDeployer hotDeployer = registry.getHotDeployer();
129 		Reloader reloader = registry.getReloader();
130 		registry.stopHotDeployer();
131 		registry.stopReloader();
132 		
133 		// Assert that there are currently no plugins
134 		assertEquals("There should be no plugins.", 0, registry.getPluginEnvironments().size());
135 		assertEquals("Resource loader should have no children.", 0, registry.getResourceLoaders().size());
136 				
137         // now let's copy a plugin over and run the hot deployer
138         String pluginZipFileLocation = new ClasspathOrFileResourceLoader().getResource("classpath:org/kuali/rice/kew/plugin/ziptest.zip").getURL().getPath();
139         File pluginZipFile = new File(pluginZipFileLocation);
140         assertTrue("Plugin file '" + pluginZipFileLocation + "' should exist", pluginZipFile.exists());
141         assertTrue("Plugin file '" + pluginZipFileLocation + "' should be a file", pluginZipFile.isFile());
142         FileUtils.copyFileToDirectory(pluginZipFile, pluginDir);
143 		
144 		// update pluginZipFile to point to the copy
145 		pluginZipFile = new File(pluginDir, pluginZipFile.getName());
146 		assertTrue(pluginZipFile.exists());
147 		
148 		// execute a hot deploy
149 		hotDeployer.run();
150 			
151 		// the plugin should have been hot deployed
152 		assertEquals("Plugin should have been hot deployed.", 1, registry.getPluginEnvironments().size());
153 		assertEquals("Resource loader should have 1 plugin child.", 1, registry.getResourceLoaders().size());
154 		PluginEnvironment environment = registry.getPluginEnvironments().get(0);
155 		Plugin plugin = environment.getPlugin();
156 		assertTrue(environment.isReloadable());
157 		assertFalse(environment.isReloadNeeded());
158 		
159 		// let's attempt to execute a Reload
160 		reloader.run();
161 		
162 		// a reload should not have occurred here since nothing was updated
163 		assertTrue("Original plugin should still be running.", plugin.isStarted());
164 		assertEquals("Plugin should not have changed.", plugin, registry.getPluginEnvironments().get(0).getPlugin());
165 		
166 		// touch the plugin file and then reload
167 		FileUtils.touch(pluginZipFile);
168 		assertTrue("A reload should be needed now.", environment.isReloadNeeded());
169 		reloader.run();
170 		
171 		// the original plugin should now be stopped
172 		assertTrue("original plugin should be stopped.", !plugin.isStarted());
173 		assertEquals("There should only be one Plugin.", 1, registry.getResourceLoaders().size());
174 		
175 		PluginEnvironment newPluginEnvironment = registry.getPluginEnvironments().get(0);
176 		Plugin newPlugin = newPluginEnvironment.getPlugin();
177 		assertEquals("There should still only be one environment.", 1, registry.getPluginEnvironments().size());
178 		assertEquals("The plugin environments should still be the same.", environment, registry.getPluginEnvironments().get(0));
179 		
180 		assertFalse("The old and new plugins should be different.", newPlugin.equals(plugin));
181 		
182 		// verify that the resource loader was updated
183 		assertEquals("The resource loaders should have been updated with the new plugin.", newPlugin, registry.getResourceLoaders().get(0));
184 		
185 	}
186 
187 	
188 }