/*******************************************************************************
 * 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("build/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("build/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("build/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("build/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("build/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("build/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("build/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("build/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("build/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("build/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("build/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("build/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();
        }
    }
}
