/*
 * Copyright 2005-2006 The Apache Software Foundation.
 *
 * Licensed 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.servicemix.jbi.installation;

import java.io.File;

import javax.jbi.component.Bootstrap;
import javax.jbi.component.Component;
import javax.jbi.component.ComponentLifeCycle;
import javax.jbi.component.ServiceUnitManager;
import javax.jbi.management.DeploymentServiceMBean;
import javax.jbi.management.InstallerMBean;
import javax.jbi.management.LifeCycleMBean;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;

import org.easymock.MockControl;

public class DeploymentTest extends AbstractManagementTest {

    // Create mocks
	protected ExtMockControl bootstrapMock;
	protected Bootstrap bootstrap;
	protected ExtMockControl componentMock;
    protected Component component;
    protected ExtMockControl lifecycleMock;
    protected ComponentLifeCycle lifecycle;
    protected ExtMockControl managerMock;
    protected ServiceUnitManager manager;
    
	protected void setUp() throws Exception {
		super.setUp();
        // Create mocks
        bootstrapMock = ExtMockControl.createControl(Bootstrap.class);                
        bootstrap = (Bootstrap) bootstrapMock.getMock();        
        Bootstrap1.setDelegate(bootstrap);
        componentMock = ExtMockControl.createControl(Component.class);
        component = (Component) componentMock.getMock();
        Component1.setDelegate(component);
        lifecycleMock = ExtMockControl.createControl(ComponentLifeCycle.class);
        lifecycle = (ComponentLifeCycle) lifecycleMock.getMock();
        managerMock = ExtMockControl.createControl(ServiceUnitManager.class);
        manager = (ServiceUnitManager) managerMock.getMock();
	}
	
	protected void reset() {
		bootstrapMock.reset();
		componentMock.reset();
		lifecycleMock.reset();
		managerMock.reset();
	}
	
	protected void replay() {
		bootstrapMock.replay();
		componentMock.replay();
		lifecycleMock.replay();
		managerMock.replay();
	}
	
	protected void verify() {
		bootstrapMock.verify();
		componentMock.verify();
		lifecycleMock.verify();
		managerMock.verify();
	}
	
	/**
     * SA is deployed and started
     * @throws Exception
     */
    public void testDeployAndStart() throws Exception {
    	// configure mocks
    	reset();
        bootstrap.init(null);
        bootstrapMock.setMatcher(MockControl.ALWAYS_MATCHER);       
        bootstrap.onInstall();
        bootstrap.getExtensionMBeanName();
        bootstrapMock.setReturnValue(null);
        bootstrap.cleanUp();
        replay();
        // test component installation
        startContainer(true);
        String installJarUrl = createInstallerArchive("component1").getAbsolutePath();
        ObjectName installerName = getInstallationService().loadNewInstaller(installJarUrl);
        InstallerMBean installer = (InstallerMBean) MBeanServerInvocationHandler.newProxyInstance(container.getMBeanServer(), installerName, InstallerMBean.class, false);
        assertFalse(installer.isInstalled());
        ObjectName lifecycleName = installer.install();
        LifeCycleMBean lifecycleMBean = (LifeCycleMBean)  MBeanServerInvocationHandler.newProxyInstance(container.getMBeanServer(), lifecycleName, LifeCycleMBean.class, false);
        assertEquals(LifeCycleMBean.SHUTDOWN, lifecycleMBean.getCurrentState());
        // check mocks
        verify();
        
        // configure mocks
        reset();
        component.getLifeCycle();
        componentMock.setReturnValue(lifecycle, MockControl.ONE_OR_MORE);
        lifecycle.init(null);
        lifecycleMock.setMatcher(MockControl.ALWAYS_MATCHER);
        lifecycle.start();
        replay();
        // test component installation
        lifecycleMBean.start();
        assertEquals(LifeCycleMBean.STARTED, lifecycleMBean.getCurrentState());
        // check mocks
        verify();
        
        // configure mocks
        reset();
        component.getServiceUnitManager();
        componentMock.setReturnValue(manager, MockControl.ONE_OR_MORE);
        manager.deploy(null, null);
        managerMock.setMatcher(MockControl.ALWAYS_MATCHER);
        managerMock.setReturnValue(null);
        replay();
        // deploy sa
        assertTrue(getDeploymentService().canDeployToComponent("component1"));
        File installSaUrl = createServiceAssemblyArchive("sa", "su", "component1");
        String result = getDeploymentService().deploy(installSaUrl.getAbsolutePath());
        System.err.println(result);
        String[] sas = getDeploymentService().getDeployedServiceAssemblies();
        assertNotNull(sas);
        assertEquals(1, sas.length);
        assertEquals("sa", sas[0]);
        sas = getDeploymentService().getDeployedServiceAssembliesForComponent("component1");
        assertNotNull(sas);
        assertEquals(1, sas.length);
        assertEquals("sa", sas[0]);
        assertEquals(DeploymentServiceMBean.SHUTDOWN, getDeploymentService().getState("sa"));
        // check mocks
        verify();
        
        // configure mocks
        reset();
        component.getServiceUnitManager();
        componentMock.setReturnValue(manager, MockControl.ZERO_OR_MORE);
        manager.init(null, null);
        managerMock.setMatcher(MockControl.ALWAYS_MATCHER);
        manager.start("su");
        replay();
        // start sa
        getDeploymentService().start("sa");
        assertEquals(DeploymentServiceMBean.STARTED, getDeploymentService().getState("sa"));
        // check mocks
        verify();
        
        // Clean shutdown
        reset();
        component.getLifeCycle();
        componentMock.setReturnValue(lifecycle, MockControl.ONE_OR_MORE);
        component.getServiceUnitManager();
        componentMock.setReturnValue(manager, MockControl.ONE_OR_MORE);
        lifecycle.stop();
        lifecycle.shutDown();
        //manager.stop("su");
        manager.shutDown("su");
        replay();
        shutdownContainer();
    }

	/**
     * SA is deployed and started
     * @throws Exception
     */
    public void testDeployAndRestart() throws Exception {
    	// configure mocks
    	reset();    	
        bootstrap.init(null);        
        bootstrapMock.setMatcher(MockControl.ALWAYS_MATCHER);        
        bootstrap.onInstall();
        bootstrap.getExtensionMBeanName();
        bootstrapMock.setReturnValue(null);
        bootstrap.cleanUp();
        replay();
        // test component installation
        startContainer(true);
        String installJarUrl = createInstallerArchive("component1").getAbsolutePath();
        ObjectName installerName = getInstallationService().loadNewInstaller(installJarUrl);
        InstallerMBean installer = (InstallerMBean) MBeanServerInvocationHandler.newProxyInstance(container.getMBeanServer(), installerName, InstallerMBean.class, false);
        assertFalse(installer.isInstalled());
        ObjectName lifecycleName = installer.install();
        LifeCycleMBean lifecycleMBean = (LifeCycleMBean)  MBeanServerInvocationHandler.newProxyInstance(container.getMBeanServer(), lifecycleName, LifeCycleMBean.class, false);
        assertEquals(LifeCycleMBean.SHUTDOWN, lifecycleMBean.getCurrentState());
        // check mocks
        verify();
        
        // configure mocks
        reset();
        component.getLifeCycle();
        componentMock.setReturnValue(lifecycle, MockControl.ONE_OR_MORE);
        lifecycle.init(null);
        lifecycleMock.setMatcher(MockControl.ALWAYS_MATCHER);
        lifecycle.start();
        replay();
        // test component installation
        lifecycleMBean.start();
        assertEquals(LifeCycleMBean.STARTED, lifecycleMBean.getCurrentState());
        // check mocks
        verify();
        
        // configure mocks
        reset();
        component.getServiceUnitManager();
        componentMock.setReturnValue(manager, MockControl.ONE_OR_MORE);
        manager.deploy(null, null);
        managerMock.setMatcher(MockControl.ALWAYS_MATCHER);
        managerMock.setReturnValue(null);
        replay();
        // deploy sa
        assertTrue(getDeploymentService().canDeployToComponent("component1"));
        File installSaUrl = createServiceAssemblyArchive("sa", "su", "component1");
        getDeploymentService().deploy(installSaUrl.getAbsolutePath());
        String[] sas = getDeploymentService().getDeployedServiceAssemblies();
        assertNotNull(sas);
        assertEquals(1, sas.length);
        assertEquals("sa", sas[0]);
        sas = getDeploymentService().getDeployedServiceAssembliesForComponent("component1");
        assertNotNull(sas);
        assertEquals(1, sas.length);
        assertEquals("sa", sas[0]);
        assertEquals(DeploymentServiceMBean.SHUTDOWN, getDeploymentService().getState("sa"));
        // check mocks
        verify();
        
        // configure mocks
        reset();
        lifecycle.stop();
        lifecycle.shutDown();
        replay();
        // shutdown container
        shutdownContainer();
        // check mocks
        verify();
        
        // configure mocks
        reset();
        // XXX Should the bootstrap re-init?
        bootstrap.init(null);
        bootstrapMock.setMatcher(MockControl.ALWAYS_MATCHER);
        bootstrap.getExtensionMBeanName();
        bootstrapMock.setReturnValue(null);
        component.getLifeCycle();
        componentMock.setReturnValue(lifecycle, MockControl.ONE_OR_MORE);
        lifecycle.init(null);
        lifecycleMock.setMatcher(MockControl.ALWAYS_MATCHER);
        lifecycle.start();        
        component.getServiceUnitManager();
        componentMock.setReturnValue(manager, MockControl.ONE_OR_MORE);
        manager.init(null, null);
        managerMock.setMatcher(MockControl.ALWAYS_MATCHER);
        manager.shutDown("su");
        replay();
        // start container
        startContainer(false);
        // check mocks
        verify();
        
        // Clean shutdown
        reset();
        component.getLifeCycle();
        componentMock.setReturnValue(lifecycle, MockControl.ONE_OR_MORE);
        component.getServiceUnitManager();
        componentMock.setReturnValue(manager, MockControl.ONE_OR_MORE);
        lifecycle.stop();
        lifecycle.shutDown();
        //manager.stop("su");
        manager.shutDown("su");
        replay();
        shutdownContainer();
    }

	/**
     * SA is deployed and started
     * @throws Exception
     */
    public void testDeployStartAndRestart() throws Exception {
    	// configure mocks
    	reset();
        bootstrap.init(null);
        bootstrapMock.setMatcher(MockControl.ALWAYS_MATCHER);
        bootstrap.onInstall();
        bootstrap.getExtensionMBeanName();
        bootstrapMock.setReturnValue(null);
        bootstrap.cleanUp();
        replay();
        // test component installation
        startContainer(true);
        String installJarUrl = createInstallerArchive("component1").getAbsolutePath();
        ObjectName installerName = getInstallationService().loadNewInstaller(installJarUrl);
        InstallerMBean installer = (InstallerMBean) MBeanServerInvocationHandler.newProxyInstance(container.getMBeanServer(), installerName, InstallerMBean.class, false);
        assertFalse(installer.isInstalled());
        ObjectName lifecycleName = installer.install();
        LifeCycleMBean lifecycleMBean = (LifeCycleMBean)  MBeanServerInvocationHandler.newProxyInstance(container.getMBeanServer(), lifecycleName, LifeCycleMBean.class, false);
        assertEquals(LifeCycleMBean.SHUTDOWN, lifecycleMBean.getCurrentState());
        // check mocks
        verify();
        
        // configure mocks
        reset();
        component.getLifeCycle();
        componentMock.setReturnValue(lifecycle, MockControl.ONE_OR_MORE);
        lifecycle.init(null);
        lifecycleMock.setMatcher(MockControl.ALWAYS_MATCHER);
        lifecycle.start();
        replay();
        // test component installation
        lifecycleMBean.start();
        assertEquals(LifeCycleMBean.STARTED, lifecycleMBean.getCurrentState());
        // check mocks
        verify();
        
        // configure mocks
        reset();
        component.getServiceUnitManager();
        componentMock.setReturnValue(manager, MockControl.ONE_OR_MORE);
        manager.deploy(null, null);
        managerMock.setMatcher(MockControl.ALWAYS_MATCHER);
        managerMock.setReturnValue(null);
        replay();
        // deploy sa
        assertTrue(getDeploymentService().canDeployToComponent("component1"));
        File installSaUrl = createServiceAssemblyArchive("sa", "su", "component1");
        getDeploymentService().deploy(installSaUrl.getAbsolutePath());
        String[] sas = getDeploymentService().getDeployedServiceAssemblies();
        assertNotNull(sas);
        assertEquals(1, sas.length);
        assertEquals("sa", sas[0]);
        sas = getDeploymentService().getDeployedServiceAssembliesForComponent("component1");
        assertNotNull(sas);
        assertEquals(1, sas.length);
        assertEquals("sa", sas[0]);
        assertEquals(DeploymentServiceMBean.SHUTDOWN, getDeploymentService().getState("sa"));
        // check mocks
        verify();
        
        // configure mocks
        reset();
        manager.init(null, null);
        managerMock.setMatcher(MockControl.ALWAYS_MATCHER);
        manager.start("su");
        replay();
        // start sa
        getDeploymentService().start("sa");
        assertEquals(DeploymentServiceMBean.STARTED, getDeploymentService().getState("sa"));
        // check mocks
        verify();
        
        // configure mocks
        reset();
        lifecycle.stop();
        lifecycle.shutDown();
        manager.stop("su");
        manager.shutDown("su");
        replay();
        // shutdown container
        shutdownContainer();
        // check mocks
        verify();
        
        // configure mocks
        reset();  
        // XXX Should the bootstrap re-init?
        bootstrap.init(null);
        bootstrapMock.setMatcher(MockControl.ALWAYS_MATCHER);
        bootstrap.getExtensionMBeanName();
        bootstrapMock.setReturnValue(null);
        component.getLifeCycle();
        componentMock.setReturnValue(lifecycle, MockControl.ONE_OR_MORE);
        lifecycle.init(null);
        lifecycleMock.setMatcher(MockControl.ALWAYS_MATCHER);
        lifecycle.start();
        component.getServiceUnitManager();
        componentMock.setReturnValue(manager, MockControl.ONE_OR_MORE);
        manager.init(null, null);
        managerMock.setMatcher(MockControl.ALWAYS_MATCHER);
        manager.start("su");
        managerMock.setMatcher(MockControl.ALWAYS_MATCHER);
        replay();
        // start container
        startContainer(false);
        // check mocks
        verify();
        
        // Clean shutdown
        reset();
        component.getLifeCycle();
        componentMock.setReturnValue(lifecycle, MockControl.ONE_OR_MORE);
        component.getServiceUnitManager();
        componentMock.setReturnValue(manager, MockControl.ONE_OR_MORE);
        lifecycle.stop();
        lifecycle.shutDown();
        //manager.stop("su");
        manager.shutDown("su");
        replay();
        shutdownContainer();
    }

}
