net.sourceforge.vulcan.spring.SpringPluginManagerTest.java Source code

Java tutorial

Introduction

Here is the source code for net.sourceforge.vulcan.spring.SpringPluginManagerTest.java

Source

/*
 * Vulcan Build Manager
 * Copyright (C) 2005-2012 Chris Eldredge
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package net.sourceforge.vulcan.spring;

import static net.sourceforge.vulcan.TestUtils.resolveRelativeFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.List;

import net.sourceforge.vulcan.EasyMockTestCase;
import net.sourceforge.vulcan.MockApplicationContext;
import net.sourceforge.vulcan.core.ConfigurationStore;
import net.sourceforge.vulcan.core.ProjectNameChangeListener;
import net.sourceforge.vulcan.core.BeanEncoder.FactoryExpert;
import net.sourceforge.vulcan.dto.ComponentVersionDto;
import net.sourceforge.vulcan.dto.PluginConfigDto;
import net.sourceforge.vulcan.dto.PluginMetaDataDto;
import net.sourceforge.vulcan.event.BrokenBuildClaimedEvent;
import net.sourceforge.vulcan.event.BuildCompletedEvent;
import net.sourceforge.vulcan.event.BuildEvent;
import net.sourceforge.vulcan.event.BuildStartingEvent;
import net.sourceforge.vulcan.event.EventHandler;
import net.sourceforge.vulcan.exception.PluginLoadFailureException;
import net.sourceforge.vulcan.exception.PluginNotConfigurableException;
import net.sourceforge.vulcan.exception.PluginNotFoundException;
import net.sourceforge.vulcan.integration.BuildManagerObserverPlugin;
import net.sourceforge.vulcan.integration.ConfigurablePlugin;
import net.sourceforge.vulcan.integration.Plugin;
import net.sourceforge.vulcan.integration.PluginStub;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.config.PropertyResourceConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

public class SpringPluginManagerTest extends EasyMockTestCase {
    BuildEventPluginPublisher buildEventPluginPublisher = new BuildEventPluginPublisher();
    SpringPluginManager mgr = new SpringPluginManager() {
        @SuppressWarnings("unchecked")
        @Override
        public synchronized <T extends Plugin> List<T> getPlugins(Class<T> type) {
            if (fakePlugins != null) {
                return (List<T>) fakePlugins;
            }
            return super.getPlugins(type);
        }
    };
    DelegatingResourceBundleMessageSource loader = new DelegatingResourceBundleMessageSource();

    ConfigurationStore store = createMock(ConfigurationStore.class);
    FactoryExpert expert = createStrictMock(FactoryExpert.class);

    List<Plugin> fakePlugins;

    @Override
    public void setUp() throws Exception {
        mgr.setConfigurationStore(store);

        mgr.setPluginBeanName("plugin");
        mgr.setMessageSource(loader);
        mgr.setBuildEventPluginPublisher(buildEventPluginPublisher);
        mgr.setEventHandler(new EventHandler() {
            public void reportEvent(net.sourceforge.vulcan.event.Event event) {
            };
        });
        mgr.setFactoryExpert(expert);

        initCalled = false;
        destroyCalled = false;
        event = null;
        nameChangeCalled = false;
    }

    public void testInstallPlugin() throws Exception {
        final InputStream stream = new ByteArrayInputStream("a".getBytes());

        expect(store.extractPlugin(stream)).andReturn(createFakePluginConfig(true));
        expert.registerPlugin((ClassLoader) anyObject(), (String) anyObject());

        replay();

        mgr.importPluginZip(stream);

        verify();
    }

    public void testImportCreatesPluginState() throws Exception {
        final PluginMetaDataDto plugin = createFakePluginConfig(true);

        final InputStream stream1 = new ByteArrayInputStream("a".getBytes());
        expect(store.extractPlugin(stream1)).andReturn(plugin);

        final InputStream stream2 = new ByteArrayInputStream("a".getBytes());
        expect(store.extractPlugin(stream2)).andReturn(plugin);

        expert.registerPlugin((ClassLoader) anyObject(), (String) anyObject());
        expectLastCall().times(2);

        replay();

        assertEquals(0, mgr.plugins.size());

        assertFalse(initCalled);
        mgr.importPluginZip(stream1);
        assertTrue(initCalled);

        assertEquals(1, mgr.plugins.size());
        assertTrue(mgr.plugins.containsKey("1"));

        mgr.importPluginZip(stream2);
        assertEquals(1, mgr.plugins.size());
        assertTrue(mgr.plugins.containsKey("1"));

        verify();
    }

    public void testImportThrowsOnBadPlugin() throws Exception {
        final PluginMetaDataDto plugin = createFakePluginConfig(false);
        final InputStream stream = new ByteArrayInputStream("a".getBytes());
        expect(store.extractPlugin(stream)).andReturn(plugin);

        store.deletePlugin(plugin.getId());

        replay();

        assertEquals(0, mgr.plugins.size());

        try {
            mgr.importPluginZip(stream);
            fail("expected exception");
        } catch (PluginLoadFailureException e) {
        }

        assertEquals(0, mgr.plugins.size());
        verify();
    }

    public void testRemovePlugin() throws Exception {
        testImportCreatesPluginState();
        destroyCalled = false;

        reset();

        store.deletePlugin("1");
        replay();

        assertEquals(1, mgr.plugins.size());

        assertFalse(destroyCalled);
        mgr.removePlugin("1");
        assertTrue(destroyCalled);
        assertEquals(0, mgr.plugins.size());
        verify();
    }

    public void testNoConfig() throws Exception {
        assertEquals(0, mgr.plugins.size());
        try {
            mgr.createPlugin(createFakePluginConfig(false), true);
            fail("expected exception");
        } catch (PluginLoadFailureException e) {
            final String message = e.getMessage();
            assertTrue(message, message.startsWith("IOException parsing XML document"));
        }
        assertEquals(0, mgr.plugins.size());
    }

    public void testConfigBeanNoExist() throws Exception {
        assertEquals(0, mgr.plugins.size());
        try {
            mgr.createPlugin(createFakePluginConfig("source/test/pluginTests/pluginWrongBeanName"), true);
            fail("expected exception");
        } catch (PluginLoadFailureException e) {
            assertTrue(e.getMessage().startsWith("No bean named 'plugin' is defined"));
        }

        assertEquals(0, mgr.plugins.size());
    }

    static boolean initCalled = false;
    static boolean destroyCalled = false;
    static boolean nameChangeCalled = false;
    static BuildEvent event = null;
    static PluginConfigDto configBean = new PluginStub();

    public static class MockPlugin implements BuildManagerObserverPlugin, ProjectNameChangeListener {
        String id;

        public void setId(String id) {
            this.id = id;
        }

        public String getId() {
            return id;
        }

        public String getName() {
            return id;
        }

        public void init() {
            initCalled = true;
        }

        public void end() {
            destroyCalled = true;
        }

        public void onBuildStarting(BuildStartingEvent evt) {
            event = evt;
        }

        public void onBuildCompleted(BuildCompletedEvent evt) {
            event = evt;
        }

        public void onBrokenBuildClaimed(BrokenBuildClaimedEvent evt) {
            event = evt;
        }

        public void projectNameChanged(String oldName, String newName) {
            nameChangeCalled = true;
        }
    }

    public static class MockPlugin2 extends MockPlugin implements ConfigurablePlugin, ApplicationContextAware {
        ApplicationContext ac;

        public PluginConfigDto getConfiguration() {
            return configBean;
        }

        public void setConfiguration(PluginConfigDto bean) {
            configBean = bean;
        }

        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            ac = applicationContext;
        }
    }

    public void testInitCreatesPluginStates() throws Exception {
        expect(store.getPluginConfigs()).andReturn(new PluginMetaDataDto[] { createFakePluginConfig(true) });

        expert.registerPlugin((ClassLoader) anyObject(), (String) anyObject());

        replay();

        assertEquals(0, mgr.plugins.size());

        mgr.init();

        verify();
        assertEquals(1, mgr.plugins.size());
        assertTrue(mgr.plugins.containsKey("1"));
    }

    public void testPluginAppCtxGetsParentPropertyPlaceholder() throws Exception {
        final PropertyResourceConfigurer cfgr = new PropertyPlaceholderConfigurer();

        final StaticApplicationContext ctx = new StaticApplicationContext();

        ctx.getBeanFactory().registerSingleton("foo", cfgr);

        ctx.refresh();

        mgr.setApplicationContext(ctx);

        expect(store.getPluginConfigs()).andReturn(new PluginMetaDataDto[] { createFakePluginConfig(true) });

        expert.registerPlugin((ClassLoader) anyObject(), (String) anyObject());

        replay();

        mgr.init();

        verify();

        assertTrue("should contain cfgr",
                mgr.plugins.get("1").context.getBeanFactoryPostProcessors().contains(cfgr));
    }

    public void testInitDoesNotDeleteFailedPlugins() throws Exception {
        final PluginMetaDataDto pluginConfig = createFakePluginConfig(false);

        expect(store.getPluginConfigs()).andReturn(new PluginMetaDataDto[] { pluginConfig });

        replay();

        assertEquals(0, mgr.plugins.size());

        mgr.init();

        verify();
        assertEquals(0, mgr.plugins.size());
    }

    public void testInitLoadsBundlesPlugins() throws Exception {
        mgr.setImportBundledPlugins(true);
        final String resourcePattern = "/plugins/*.zip";
        final FileSystemResource resource = new FileSystemResource(
                resolveRelativeFile("source/test/pluginTests/mockPlugin.zip"));

        mgr.setBundledPluginResourcesPattern(resourcePattern);
        final MockApplicationContext ctx = new MockApplicationContext() {
            @Override
            public Resource[] getResources(String locationPattern) throws java.io.IOException {
                assertEquals(resourcePattern, locationPattern);
                return new Resource[] { resource };
            };
        };
        ctx.refresh();
        mgr.setApplicationContext(ctx);

        final PluginMetaDataDto pluginConfig = createFakePluginConfig(true);

        expect(store.extractPlugin((InputStream) anyObject())).andReturn(pluginConfig);

        expect(store.getPluginConfigs()).andReturn(new PluginMetaDataDto[] { pluginConfig });
        expert.registerPlugin((ClassLoader) anyObject(), (String) anyObject());

        replay();

        assertEquals(0, mgr.plugins.size());

        mgr.init();

        verify();
        assertEquals(1, mgr.plugins.size());
    }

    public void testShutdownStopsPlugins() throws Exception {
        assertFalse(destroyCalled);

        testInitCreatesPluginStates();

        assertFalse(destroyCalled);

        mgr.shutdown();

        assertTrue(destroyCalled);
    }

    public void testCallsBuildManagerObservers() throws Exception {
        expect(store.getPluginConfigs()).andReturn(new PluginMetaDataDto[] { createFakePluginConfig(true) });

        expert.registerPlugin((ClassLoader) anyObject(), (String) anyObject());

        replay();

        assertEquals(0, mgr.plugins.size());

        mgr.init();

        verify();
        assertEquals(1, mgr.plugins.size());
        assertTrue(mgr.plugins.containsKey("1"));

        assertEquals(null, event);

        final EventBridge e = new EventBridge(new BuildCompletedEvent(this, null, null, null));
        buildEventPluginPublisher.onApplicationEvent(e);

        assertSame(e.getEvent(), event);
    }

    public void testCallsProjectNameChanged() throws Exception {
        expect(store.getPluginConfigs()).andReturn(new PluginMetaDataDto[] { createFakePluginConfig(true) });
        expert.registerPlugin((ClassLoader) anyObject(), (String) anyObject());

        replay();
        mgr.init();
        verify();

        assertFalse(nameChangeCalled);

        mgr.projectNameChanged("oldy", "newy");

        assertTrue(nameChangeCalled);
    }

    public void testGetPlugins() throws Exception {
        mgr.createPlugin(createFakePluginConfig("source/test/pluginTests/goodPlugin"), true);
        mgr.createPlugin(createFakePluginConfig("source/test/pluginTests/goodPlugin2"), true);

        assertEquals(2, mgr.plugins.size());

        final List<Plugin> plugins = mgr.getPlugins(Plugin.class);

        assertNotNull(plugins);

        assertEquals(2, plugins.size());

        assertEquals("1", plugins.get(0).getId());
        assertEquals("2", plugins.get(1).getId());
    }

    public void testGetInfoNoPlugin() throws Exception {
        try {
            mgr.getPluginConfigInfo("1");
            fail("expected exception");
        } catch (PluginNotFoundException e) {
            assertEquals("1", e.getPluginId());
        }
    }

    public void testGetPluginVersions() throws Exception {
        mgr.createPlugin(createFakePluginConfig("source/test/pluginTests/goodPlugin"), true);
        mgr.createPlugin(createFakePluginConfig("source/test/pluginTests/goodPlugin2"), true);

        final List<ComponentVersionDto> versions = mgr.getPluginVersions();
        assertNotNull(versions);

        assertEquals(2, versions.size());

        assertEquals("1", versions.get(0).getId());
        assertEquals("1", versions.get(0).getName());
        assertEquals("2", versions.get(1).getId());
        assertEquals("2", versions.get(1).getName());
    }

    public void testGetInfoNotConfigurable() throws Exception {
        final PluginMetaDataDto plugin = createFakePluginConfig("source/test/pluginTests/goodPlugin");

        mgr.createPlugin(plugin, true);

        try {
            mgr.getPluginConfigInfo("1");
            fail("expected exception");
        } catch (PluginNotConfigurableException e) {
        }
    }

    public void testGetInfo() throws Exception {
        final PluginMetaDataDto plugin = createFakePluginConfig("source/test/pluginTests/goodPlugin2");

        assertNotNull(configBean);

        mgr.createPlugin(plugin, true);

        final Object bean = mgr.getPluginConfigInfo(plugin.getId());
        assertSame(configBean, bean);
    }

    public void testCreateObject() throws Exception {
        final PluginMetaDataDto plugin = createFakePluginConfig("source/test/pluginTests/goodPlugin2");
        mgr.createPlugin(plugin, true);

        final Object bean = mgr.getPluginConfigInfo(plugin.getId());

        final Object bean2 = mgr.createObject(plugin.getId(), bean.getClass().getName());

        assertNotSame(bean, bean2);
    }

    public void testCreateApplicationContextAwareObject() throws Exception {
        final PluginMetaDataDto plugin = createFakePluginConfig("source/test/pluginTests/goodPlugin2");
        mgr.createPlugin(plugin, true);

        final MockPlugin2 bean2 = (MockPlugin2) mgr.createObject(plugin.getId(), MockPlugin2.class.getName());

        assertNotNull(bean2.ac);

        assertSame(mgr.findPluginState(plugin.getId()).context, bean2.ac);
    }

    public static enum E {
        A, B
    };

    public void testCreateEnum() throws Exception {
        final PluginMetaDataDto plugin = createFakePluginConfig("source/test/pluginTests/goodPlugin2");
        mgr.createPlugin(plugin, true);

        final Enum<?> e = mgr.createEnum(plugin.getId(), E.class.getName(), "A");

        assertEquals(E.A, e);
    }

    public void testChildContextFormatsMessage() throws Exception {
        final PluginMetaDataDto plugin = createFakePluginConfig("source/test/pluginTests/goodPlugin2");
        mgr.createPlugin(plugin, true);

        final SpringPluginManager.PluginState state = mgr.plugins.get(plugin.getId());

        assertEquals("good afternoon.", state.context.getMessage("plugin.message", null, null));
    }

    private PluginMetaDataDto createFakePluginConfig(boolean valid) {
        if (valid)
            return createFakePluginConfig("source/test/pluginTests/goodPlugin");

        return createFakePluginConfig("source/test/pluginTests/noSuchPlugin");
    }

    int count = 1;

    private PluginMetaDataDto createFakePluginConfig(String path) {
        final PluginMetaDataDto cfg = new PluginMetaDataDto();
        cfg.setId(Integer.toString(count++));
        final File dir = resolveRelativeFile(path);
        cfg.setDirectory(dir);
        cfg.setClassPath(new URL[] {});

        return cfg;
    }
}