/**
 *  Copyright (C) 2008 Progress Software, Inc. All rights reserved.
 *  http://fusesource.com
 *
 *  The software in this package is published under the terms of the AGPL license
 *  a copy of which has been included with this distribution in the license.txt file.
 */
package org.fusesource.cloudmix.agent.karaf;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

import junit.framework.TestCase;

import org.apache.felix.karaf.admin.AdminService;
import org.apache.felix.karaf.admin.Instance;
import org.apache.felix.karaf.admin.InstanceSettings;
import org.easymock.EasyMock;
import org.fusesource.cloudmix.agent.Feature;
import org.fusesource.cloudmix.common.GridClient;
import org.fusesource.cloudmix.common.dto.ProvisioningAction;
import org.fusesource.cloudmix.common.util.FileUtils;

/**
 * Test cases for using the Karaf agent to create new Karaf instances on the fly
 */
public class KarafAgentInstancesTest extends TestCase {
    private static final String ORIGINAL_REPOSITORY 
        = "mvn:org.apache.felix.karaf/features/RELEASE/xml/features";
    private static final String REPOSITORY = "mvn:org.fusesource.cloudmix/features/1.3-SNAPSHOT/xml/features";
    private static final String ORIGINAL_FEATURE = "webconsole";
    private static final String FEATURE = "cloudmix.agent";

    private GridClient cl;
    private AdminService service;
    private KarafAgent agent;
    private List<Feature> agentFeatures = new LinkedList<Feature>();

    private File workdir;


    @Override
    protected void setUp() throws Exception {
        cl = EasyMock.createNiceMock(GridClient.class);
        EasyMock.replay(cl);

        agent = new KarafAgent() {
            @Override
            public GridClient getClient() {
                return cl;
            }

            @Override
            protected void addAgentFeature(Feature feature) {
                super.addAgentFeature(feature);
                agentFeatures.add(feature);
            }
        };
        workdir = new File("testworkdir");
        FileUtils.createDirectory(workdir);

        service = new MockAdminService();

        agent.setAdminService(service);
        agent.setWorkDirectory(workdir);
        agent.setDetailsPropertyFilePath(workdir.getAbsolutePath() + "/agent.properties");
    }

    @Override
    protected void tearDown() throws Exception {
        if (workdir != null) {
            FileUtils.deleteDirectory(workdir);
        }
    }

    /*
     * Test creating a new Karaf instance through the AdminService
     */
    public void testCreateNewInstance() throws Exception {
        ProvisioningAction action = new ProvisioningAction();
        action.setId("my-action-id");
        action.setFeature("my-feature-name");

        agent.installFeatures(action, null, "karaf:instance");
        assertEquals("One instance should have been created", 1, service.getInstances().length);
        assertEquals("One agent feature should have registered", 1, agentFeatures.size());

        Instance instance = service.getInstances()[0];
        assertEquals("Instance should have been started", Instance.STARTED, instance.getState());

        // now, let's uninstall the agent feature to destroy the instance
        agent.uninstallFeature(agentFeatures.get(0));
        assertEquals("Instance should have been stopped", Instance.STOPPED, instance.getState());
        assertEquals("Instance should have been destroyed", 0, service.getInstances().length);
    }

    /*
     * Test creating a new Karaf instance through the AdminService, specifying the initial list of feature
     * repositories and features to be installed from them
     */
    public void testCreateNewInstanceWithFeature() throws Exception {
        ProvisioningAction action = new ProvisioningAction();
        action.setId("my-action-id");
        action.setFeature("my-feature-name");

        agent.installFeatures(action, null, "karaf:instance " + REPOSITORY + " " + FEATURE);
        assertEquals("One instance should have been created", 1, service.getInstances().length);
        assertEquals("One agent feature should have registered", 1, agentFeatures.size());

        Instance instance = service.getInstances()[0];
        assertEquals("Instance should have been started", Instance.STARTED, instance.getState());
        File etc = new File(instance.getLocation(), "etc");
        Properties config = new Properties();
        config.load(new FileInputStream(new File(etc, "org.apache.felix.karaf.features.cfg")));

        assertTrue("Features repository url should have been added", config
            .getProperty(KarafAgent.FEATURES_REPOSITORIES).contains(REPOSITORY));
        assertEquals("There should be two repositories listed in total", 2, config
            .getProperty(KarafAgent.FEATURES_REPOSITORIES).split(",").length);
        assertTrue("Boot feature should have been added", config.getProperty(KarafAgent.FEATURES_BOOT)
            .contains(FEATURE));
        assertEquals("There should be two boot features listed in total", 2, config
            .getProperty(KarafAgent.FEATURES_BOOT).split(",").length);

        // now, let's uninstall the agent feature to destroy the instance
        agent.uninstallFeature(agentFeatures.get(0));
        assertEquals("Instance should have been stopped", Instance.STOPPED, instance.getState());
        assertEquals("Instance should have been destroyed", 0, service.getInstances().length);
    }

    /*
     * Test the conversion of a feature name into a valid Karaf instance name
     */
    public void testGetInstanceName() throws Exception {
        assertEquals("Replace : by _ when determining the instance name",
                     "ceffbab3-bc3d-4c72-a89c-154ab2052971_my-feature", agent
                         .getInstanceName("ceffbab3-bc3d-4c72-a89c-154ab2052971:my-feature"));
    }

    /*
     * Mock AdminService implementation
     */
    private class MockAdminService implements AdminService {

        private final class MockAdminInstance implements Instance {
            private final String name;
            private String state;
            private File location;

            private MockAdminInstance(String name) {
                this.name = name;
                location = new File("target/instances/" + name);
            }

            public void stop() throws Exception {
                state = STOPPED;
            }

            public void start(String arg0) throws Exception {
                state = STARTED;
            }

            public String getState() throws Exception {
                return state;
            }

            public int getPort() {
                return 0;
            }

            public int getPid() {
                return 0;
            }

            public String getName() {
                return name;
            }

            public String getLocation() {
                return location.getAbsolutePath();
            }

            public void destroy() throws Exception {
                instances.remove(getName());
            }

            public void changePort(int arg0) throws Exception {
                throw new UnsupportedOperationException("Not implemented");
            }
   
            
        }

        private Map<String, Instance> instances = new HashMap<String, Instance>();


        public Instance createInstance(String name, InstanceSettings settings) throws Exception {
            assertEquals("The agent should not assign a port number", 0, settings.getPort());
            assertNull("The agent should not assign a location", settings.getLocation());

            Instance instance = new MockAdminInstance(name);
            createInstanceLocation(instance);
            instances.put(name, instance);
            return instance;

        }

        private void createInstanceLocation(Instance instance) throws IOException {
            File etc = new File(instance.getLocation(), "etc");
            etc.mkdirs();

            Properties properties = new Properties();
            properties.setProperty(KarafAgent.FEATURES_REPOSITORIES, ORIGINAL_REPOSITORY);
            properties.setProperty(KarafAgent.FEATURES_BOOT, ORIGINAL_FEATURE);
            properties.store(new FileOutputStream(new File(etc, "org.apache.felix.karaf.features.cfg")),
                             "Default repository and feature created from mock AdminService");
        }

        public Instance getInstance(String name) {
            return instances.get(name);
        }

        public Instance[] getInstances() {
            return instances.values().toArray(new Instance[] {});
        }
    }
}

@@ -7307,21 +7307,98 @@
       %7D%0A
+%0A
    
-%0A
  
+        public boolean isRoot() %7B%0A                return false;%0A            %7D
         

fix compile error