/* * $Id: TestTilesPlugin.java 557933 2007-07-20 09:15:51Z apetrelli $ * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.struts.tiles2; import java.lang.reflect.InvocationTargetException; import javax.servlet.ServletException; import junit.framework.Test; import junit.framework.TestSuite; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.Globals; import org.apache.struts.action.PlugIn; import org.apache.struts.config.ModuleConfig; import org.apache.struts.config.ModuleConfigFactory; import org.apache.struts.config.PlugInConfig; import org.apache.struts.mock.MockActionServlet; import org.apache.struts.mock.TestMockBase; import org.apache.struts.util.RequestUtils; import org.apache.tiles.TilesContainer; import org.apache.tiles.access.TilesAccess; import org.apache.tiles.definition.DefinitionsFactory; import org.apache.tiles.impl.BasicTilesContainer; import org.apache.tiles.impl.KeyedDefinitionsFactoryTilesContainer; /** * Tests the Tiles plugin. * * @version $Rev: 557933 $ $Date: 2007-07-20 11:15:51 +0200 (Ven, 20 jul 2007) $ */ public class TestTilesPlugin extends TestMockBase { /** * The first module to configure. */ protected ModuleConfig module1; /** * The second module to configure. */ protected ModuleConfig module2; /** * A testing action servlet. */ protected MockActionServlet actionServlet; /** * The logging object. */ private static final Log LOG = LogFactory.getLog(TestTilesPlugin.class); // ----------------------------------------------------------------- Basics /** * Constructor. * * @param name The name of the test. */ public TestTilesPlugin(String name) { super(name); } /** * Sample main method. * * @param args Arguments. */ public static void main(String[] args) { junit.awtui.TestRunner.main(new String[] { TestTilesPlugin.class .getName() }); } /** * Test suite method. * * @return The test. */ public static Test suite() { return (new TestSuite(TestTilesPlugin.class)); } // ----------------------------------------------------- Instance Variables // ----------------------------------------------------- Setup and Teardown /** {@inheritDoc} */ public void setUp() { super.setUp(); actionServlet = new MockActionServlet(context, config); } /** {@inheritDoc} */ public void tearDown() { super.tearDown(); } // ------------------------------------------------------- Individual Tests // ---------------------------------------------------------- absoluteURL() /** * Test multi factory creation when moduleAware=true. * * @throws ServletException * If something goes wrong during initialization. * @throws InvocationTargetException * Bean properties problems. * @throws InstantiationException * Bean properties problems. * @throws IllegalAccessException * Bean properties problems. * @throws ClassNotFoundException * Bean properties problems. */ public void testMultiFactory() throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, ServletException { // init TilesPlugin module1 = createModuleConfig("/module1", "tiles-defs.xml", true); module2 = createModuleConfig("/module2", "tiles-defs.xml", true); initModulePlugIns(module1); initModulePlugIns(module2); // mock request context request.setAttribute(Globals.MODULE_KEY, module1); request.setPathElements("/myapp", "/module1/foo.do", null, null); // Retrieve TilesContainer TilesContainer container = TilesAccess.getContainer(actionServlet .getServletContext()); assertSame(container.getClass().getName(), KeyedDefinitionsFactoryTilesContainer.class.getName()); // Retrieve factory for module1 DefinitionsFactory factory1 = ((KeyedDefinitionsFactoryTilesContainer) container) .getDefinitionsFactory("/module1"); assertNotNull("factory found", factory1); // mock request context request.setAttribute(Globals.MODULE_KEY, module2); request.setPathElements("/myapp", "/module2/foo.do", null, null); // Retrieve factory for module2 DefinitionsFactory factory2 = ((KeyedDefinitionsFactoryTilesContainer) container) .getDefinitionsFactory("/module2"); assertNotNull("factory found", factory2); // Check that factory are different // FIXME This assert fails! assertNotSame("Factory from different modules", factory1, factory2); } /** * Tests if the TilesPlugin does a fail-fast on multiple configuration of * the same module. * * @throws ServletException If something goes wrong during initialization. * @throws InvocationTargetException Bean properties problems. * @throws InstantiationException Bean properties problems. * @throws IllegalAccessException Bean properties problems. * @throws ClassNotFoundException Bean properties problems. */ public void testMultiModuleFailFast() throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, ServletException { // init TilesPlugin module1 = createModuleConfig("/module1", "tiles-defs.xml", true); // The name is "/module1" on purpose module2 = createModuleConfig("/module1", "tiles-defs.xml", true); initModulePlugIns(module1); try { initModulePlugIns(module2); fail("An exception should have been thrown"); } catch (ServletException e) { // It is ok LOG.debug("Intercepted a ServletException, it is ok", e); } } /** * Test single factory creation when moduleAware=false. * * @throws ServletException If something goes wrong during initialization. * @throws InvocationTargetException Bean properties problems. * @throws InstantiationException Bean properties problems. * @throws IllegalAccessException Bean properties problems. * @throws ClassNotFoundException Bean properties problems. */ public void testSingleSharedFactory() throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, ServletException { // init TilesPlugin module1 = createModuleConfig("/module1", "tiles-defs.xml", false); module2 = createModuleConfig("/module2", "tiles-defs.xml", false); initModulePlugIns(module1); try { initModulePlugIns(module2); fail("An exception should have been thrown"); } catch (ServletException e) { // It is ok LOG.debug("Intercepted a ServletException, it is ok", e); } // mock request context request.setAttribute(Globals.MODULE_KEY, module1); request.setPathElements("/myapp", "/module1/foo.do", null, null); // Retrieve TilesContainer TilesContainer container = TilesAccess.getContainer(actionServlet .getServletContext()); assertSame(container.getClass().getName(), BasicTilesContainer.class .getName()); // Retrieve factory for module1 DefinitionsFactory factory1 = ((BasicTilesContainer) container) .getDefinitionsFactory(); assertNotNull("factory found", factory1); // mock request context request.setAttribute(Globals.MODULE_KEY, module2); request.setPathElements("/myapp", "/module2/foo.do", null, null); // Retrieve factory for module2 DefinitionsFactory factory2 = ((BasicTilesContainer) container) .getDefinitionsFactory(); assertNotNull("factory found", factory2); // Check that factory are different assertEquals("Same factory", factory1, factory2); } /** * Create a module configuration. * * @param moduleName The name of the module. * @param configFileName The name of the configuration file. * @param moduleAware <code>true</code> if the configuration must be * module-aware. * @return The configuration object. */ private ModuleConfig createModuleConfig(String moduleName, String configFileName, boolean moduleAware) { ModuleConfig moduleConfig = ModuleConfigFactory.createFactory() .createModuleConfig(moduleName); context.setAttribute(Globals.MODULE_KEY + moduleName, moduleConfig); // Set tiles plugin PlugInConfig pluginConfig = new PlugInConfig(); pluginConfig.setClassName("org.apache.struts.tiles2.TilesPlugin"); pluginConfig.addProperty("moduleAware", (moduleAware ? "true" : "false")); pluginConfig.addProperty("definitions-config", "/org/apache/struts/tiles2/config/" + configFileName); moduleConfig.addPlugInConfig(pluginConfig); return moduleConfig; } /** * Fake call to init module plugins. * * @param moduleConfig The configuration of the module. * @throws ServletException If something goes wrong during initialization. * @throws InvocationTargetException Bean properties problems. * @throws InstantiationException Bean properties problems. * @throws IllegalAccessException Bean properties problems. * @throws ClassNotFoundException Bean properties problems. */ private void initModulePlugIns(ModuleConfig moduleConfig) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, ServletException { PlugInConfig[] plugInConfigs = moduleConfig.findPlugInConfigs(); PlugIn[] plugIns = new PlugIn[plugInConfigs.length]; context.setAttribute(Globals.PLUG_INS_KEY + moduleConfig.getPrefix(), plugIns); for (int i = 0; i < plugIns.length; i++) { plugIns[i] = (PlugIn) RequestUtils .applicationInstance(plugInConfigs[i].getClassName()); BeanUtils.populate(plugIns[i], plugInConfigs[i].getProperties()); // Pass the current plugIn config object to the PlugIn. // The property is set only if the plugin declares it. // This plugin config object is needed by Tiles BeanUtils.copyProperty(plugIns[i], "currentPlugInConfigObject", plugInConfigs[i]); plugIns[i].init(actionServlet, moduleConfig); } } }