/*******************************************************************************
 * Copyright (c) 2008, 2010 VMware Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   VMware Inc. - initial contribution
 *******************************************************************************/

package org.eclipse.virgo.repository.internal.watched;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.Version;

import org.eclipse.virgo.medic.test.eventlog.MockEventLogger;
import org.eclipse.virgo.repository.ArtifactBridge;
import org.eclipse.virgo.repository.ArtifactDescriptor;
import org.eclipse.virgo.repository.ArtifactGenerationException;
import org.eclipse.virgo.repository.IndexFormatException;
import org.eclipse.virgo.repository.RepositoryAwareArtifactDescriptor;
import org.eclipse.virgo.repository.RepositoryCreationException;
import org.eclipse.virgo.repository.builder.ArtifactDescriptorBuilder;
import org.eclipse.virgo.repository.builder.AttributeBuilder;
import org.eclipse.virgo.repository.configuration.WatchedStorageRepositoryConfiguration;
import org.eclipse.virgo.repository.internal.LocalRepository;
import org.eclipse.virgo.repository.internal.watched.WatchedStorageRepository;
import org.eclipse.virgo.util.io.FileCopyUtils;
import org.eclipse.virgo.util.osgi.manifest.VersionRange;

/**
 * Test the {@link WatchedStorageRepository} extension of the {@link LocalRepository} class.
 * <p />
 * 
 * <strong>Concurrent Semantics</strong><br />
 * Thread-safe
 * 
 */
public class WatchedStorageRepositoryTests {

    private static final String LOCATIONS_TEST_FILENAME = "a.jar";

    private static final String MBEAN_DOMAIN_VIRGO_WEB_SERVER = "org.eclipse.virgo.server";

    private static MockEventLogger mockEventLogger = new MockEventLogger();

    private static final String ARTIFACT_FILE_NAME = "org.eclipse.virgo.sample.configuration.properties.core.jar";

    private static final String WATCHED_REPO_NAME = "Test-Watched-Repo";

    private static final int WATCH_INTERVAL = 5; // seconds

    private static final int MIN_WATCH_INTERVAL = 1; // seconds

    private static final int LONG_WATCH_INTERVAL = 50; // seconds

    private static final int BAD_WATCH_INTERVAL = 0; // seconds

    private static final File testArtefactFile1 = new File("src/test/resources/artifacts/" + ARTIFACT_FILE_NAME);

    private WatchedStorageRepositoryConfiguration wsrConfiguration;

    private WatchedStorageRepository wsRepository;

    private final File watchDir = new File("target/watchedDir");

    private Set<ArtifactBridge> artefactBridgeDefinitions;

    @Before
    public void setUp() {
        mockEventLogger.reinitialise();
        this.watchDir.mkdirs();
        this.artefactBridgeDefinitions = new HashSet<ArtifactBridge>(4);
        this.artefactBridgeDefinitions.add(new StaticBridge());
        assertTrue("Need jar artifact for tests.", testArtefactFile1.exists());
    }

    @Test
    public void testConstructor() throws RepositoryCreationException, IndexFormatException {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            WATCH_INTERVAL, null);

        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, new MockEventLogger());
        assertFalse("Didn't create a repository!", null == this.wsRepository);
    }

    @Test
    public void testConstructLongWaiter() throws RepositoryCreationException, IndexFormatException {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            LONG_WATCH_INTERVAL, null);

        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);

        assertFalse("Didn't create a repository!", null == this.wsRepository);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testConstructorBadWaiter() throws RepositoryCreationException, IndexFormatException {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            BAD_WATCH_INTERVAL, null);

        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);

        assertTrue("Created a repository after exception!", null == this.wsRepository);
    }

    @Test
    public void testGetArtifactLocations() throws Exception {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            WATCH_INTERVAL, null);
        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
        assertFalse("Didn't create a repository!", null == this.wsRepository);

        Set<String> locations = this.wsRepository.getArtifactLocations(LOCATIONS_TEST_FILENAME);
        Set<String> expectedLocations = new HashSet<String>(1);
        expectedLocations.add(new File(this.watchDir,LOCATIONS_TEST_FILENAME).getCanonicalPath());
        assertNotNull("null locations set returned.", locations);
        assertEquals("set of locations not expected", expectedLocations, locations);
    }
    
    @Test
    public void testGetOnEmptyRepository() throws RepositoryCreationException, IOException {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            WATCH_INTERVAL, null);

        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
        
        assertFalse("Didn't create a repository!", null == this.wsRepository);

        this.wsRepository.start(); // must start it to see things

        VersionRange maxRange = new VersionRange("0");
        ArtifactDescriptor aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
        assertTrue("A descriptor returned, when it shouldn't!", null == aD);

        this.wsRepository.stop(); // tidy up after one!
    }

    @Test
    public void testGetInitialArtefact() throws RepositoryCreationException, IOException {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            MIN_WATCH_INTERVAL, null);

        putArtifactFile(testArtefactFile1);

        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
        assertFalse("Didn't create a repository!", null == this.wsRepository);

        this.wsRepository.start(); // must start it to see things

        testDelay(MIN_WATCH_INTERVAL);
        VersionRange maxRange = new VersionRange("0");
        ArtifactDescriptor aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
        assertTrue("Wrong or null descriptor returned!", (null == aD ? false : aD.getName().equals(testArtefactFile1.getName())));

        this.wsRepository.stop(); // tidy up after one!
    }

    @Test
    public void testGetInitialArtefactWithCheck() throws Exception {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            MIN_WATCH_INTERVAL, null);

        putArtifactFile(testArtefactFile1);

        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
        assertFalse("Didn't create a repository!", null == this.wsRepository);

        this.wsRepository.start(); // must start it to see things

        this.wsRepository.forceCheck();
        
        VersionRange maxRange = new VersionRange("0");
        ArtifactDescriptor aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
        assertTrue("Wrong or null descriptor returned!", (null == aD ? false : aD.getName().equals(testArtefactFile1.getName())));

        this.wsRepository.stop(); // tidy up after one!
    }

    /**
     * Short delay (of seconds) in test
     */
    private void testDelay(long secs) {
        try {
            Thread.sleep(secs * 1000);
        } catch (InterruptedException e) {
            // continue
        }
    }

    @Test
    public void testGetAddAndDeleteArtefact() throws RepositoryCreationException, IOException {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            MIN_WATCH_INTERVAL, null);

        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, new MockEventLogger());
        assertFalse("Didn't create a repository!", null == this.wsRepository);

        this.wsRepository.start(); // must start it to see things

        putArtifactFile(testArtefactFile1);

        testDelay(3 * MIN_WATCH_INTERVAL);

        VersionRange maxRange = new VersionRange("0");
        RepositoryAwareArtifactDescriptor aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
        assertNotNull("Null descriptor returned.", aD);
        assertEquals(testArtefactFile1.getName(), aD.getName());
        assertEquals("static", aD.getType());
        assertEquals(new Version(0, 1, 0), aD.getVersion());

        removeArtifactFile(testArtefactFile1);

        testDelay(2 * MIN_WATCH_INTERVAL);

        aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
        assertTrue("A descriptor returned, when it shouldn't!", null == aD);

        this.wsRepository.stop(); // tidy up after one!
    }
    
    @Test
    public void testGetAddAndDeleteArtefactWithCheck() throws RepositoryCreationException, IOException, ArtifactGenerationException, Exception {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            MIN_WATCH_INTERVAL, null);

        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, new MockEventLogger());
        assertFalse("Didn't create a repository!", null == this.wsRepository);

        this.wsRepository.start(); // watcher needs to be created
        
        putArtifactFile(testArtefactFile1);

        this.wsRepository.forceCheck();

        VersionRange maxRange = new VersionRange("0");
        RepositoryAwareArtifactDescriptor aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
        assertNotNull("Null descriptor returned.", aD);
        assertEquals(testArtefactFile1.getName(), aD.getName());
        assertEquals("static", aD.getType());
        assertEquals(new Version(0, 1, 0), aD.getVersion());

        removeArtifactFile(testArtefactFile1);

        this.wsRepository.forceCheck();

        aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
        assertTrue("A descriptor returned, when it shouldn't!", null == aD);

        this.wsRepository.stop(); // tidy up after one!
    }

    @Test
    public void mBeanPublication() throws Exception {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            WATCH_INTERVAL, MBEAN_DOMAIN_VIRGO_WEB_SERVER);

        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
        ObjectName objectName = new ObjectName(MBEAN_DOMAIN_VIRGO_WEB_SERVER + ":type=Repository,name=" + WATCHED_REPO_NAME);
        MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();

        try {
            platformMBeanServer.getMBeanInfo(objectName);
            fail("MBean should not be present until repository has been started");
        } catch (InstanceNotFoundException infe) {
        }

        this.wsRepository.start();

        MBeanInfo mBeanInfo = platformMBeanServer.getMBeanInfo(objectName);
        Object type = mBeanInfo.getDescriptor().getFieldValue("type");
        assertNotNull(type);
        assertEquals("watched", type);

        this.wsRepository.stop();

        try {
            platformMBeanServer.getMBeanInfo(objectName);
            fail("MBean should not be present once repository has been stopped");
        } catch (InstanceNotFoundException infe) {
        }
    }

    @Test
    public void mBeanNonPublication() throws Exception {
        this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("target/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
            WATCH_INTERVAL, null);
        this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
        ObjectName objectName = new ObjectName(MBEAN_DOMAIN_VIRGO_WEB_SERVER + ":type=Repository,name=" + WATCHED_REPO_NAME);
        MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();

        try {
            platformMBeanServer.getMBeanInfo(objectName);
            fail("MBean should not be present before start");
        } catch (InstanceNotFoundException infe) {
        }

        this.wsRepository.start();

        try {
            platformMBeanServer.getMBeanInfo(objectName);
            fail("MBean should not be present after start");
        } catch (InstanceNotFoundException infe) {
        }

        this.wsRepository.stop();

        try {
            platformMBeanServer.getMBeanInfo(objectName);
            fail("MBean should not be present once repository has been stopped");
        } catch (InstanceNotFoundException infe) {
        }
    }

    /**
     * Put artefact file copy into watched directory
     * 
     * @throws IOException
     */
    private File putArtifactFile(File artifactFile) throws IOException {
        File toFile = new File(this.watchDir, artifactFile.getName());
        FileCopyUtils.copy(artifactFile, toFile);
        assertTrue("Failed to copy file into watched directory", toFile.exists());
        return toFile;
    }

    /**
     * Remove artefact file copy from watched directory
     * 
     * @throws IOException
     */
    private void removeArtifactFile(File artifactFile) throws IOException {
        File fileToRemove = new File(this.watchDir, artifactFile.getName());
        fileToRemove.delete();
        assertFalse("Failed to delete file from watched directory", fileToRemove.exists());
    }

    @After
    public void stop() {
        if (null != this.wsRepository) {
            this.wsRepository.stop();
        }
        if (this.watchDir.isDirectory()) {
            if (this.watchDir.exists()) {
                for (File file : this.watchDir.listFiles()) {
                    file.delete();
                }
                this.watchDir.delete();
            }
        }
    }

    /**
     * <p>
     * Implementation of <code>ArtefactBridge</code> that understands how to create a minimal Artefact from any given
     * file. The Artefact name will be that of the file including any extension and the version will always be '0'. The
     * number of bytes in the file, as reported by the operating system will be added as the sole Attribute with a name
     * of size.
     * </p>
     * 
     * <strong>Concurrent Semantics</strong><br />
     * 
     * This class is Threadsafe
     * 
     */
    private class StaticBridge implements ArtifactBridge {

        public static final String STATIC_ARTIFACT_TYPE = "static";

        public static final String ARTEFACT_ATTRIBUTE_SIZE = "size";

        /**
         * {@inheritDoc}
         */
        public ArtifactDescriptor generateArtifactDescriptor(File artifact) throws ArtifactGenerationException {
            if (!artifact.exists()) {
                throw new ArtifactGenerationException("Artifact must exist at the specified location: " + artifact.getAbsolutePath(),
                    STATIC_ARTIFACT_TYPE);
            }
            ArtifactDescriptorBuilder builder = new ArtifactDescriptorBuilder();
            builder.setUri(artifact.toURI());
            builder.setType(STATIC_ARTIFACT_TYPE);
            builder.setName(artifact.getName());
            builder.setVersion("0.1.0");

            //Exercise the Attribute builder class a bit
            AttributeBuilder attrBuilder = new AttributeBuilder().setName(ARTEFACT_ATTRIBUTE_SIZE);
            attrBuilder.setValue(String.valueOf(artifact.length()));
            attrBuilder.putProperties("key1","value1");
            ArrayList<String> valueList = new ArrayList<String>(1);
            valueList.add("value2");
            attrBuilder.putProperties("key2",valueList);

            builder.addAttribute(attrBuilder.build());

            return builder.build();
        }
    }
}
