/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.jackrabbit.vault.packaging.integration;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

import javax.jcr.RepositoryException;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
import org.apache.jackrabbit.vault.fs.io.ImportOptions;
import org.apache.jackrabbit.vault.packaging.Dependency;
import org.apache.jackrabbit.vault.packaging.DependencyException;
import org.apache.jackrabbit.vault.packaging.NoSuchPackageException;
import org.apache.jackrabbit.vault.packaging.PackageException;
import org.apache.jackrabbit.vault.packaging.PackageExistsException;
import org.apache.jackrabbit.vault.packaging.PackageId;
import org.apache.jackrabbit.vault.packaging.registry.DependencyReport;
import org.apache.jackrabbit.vault.packaging.registry.ExecutionPlan;
import org.apache.jackrabbit.vault.packaging.registry.ExecutionPlanBuilder;
import org.apache.jackrabbit.vault.packaging.registry.PackageTask;
import org.apache.jackrabbit.vault.packaging.registry.RegisteredPackage;
import org.apache.jackrabbit.vault.packaging.registry.PackageTask.Type;
import org.apache.jackrabbit.vault.packaging.registry.impl.FSInstallState;
import org.apache.jackrabbit.vault.packaging.registry.impl.FSPackageRegistry;
import org.apache.jackrabbit.vault.packaging.registry.impl.FSPackageStatus;
import org.apache.jackrabbit.vault.packaging.registry.impl.InstallationScope;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * Test the Package registry interface
 */
public class TestFSPackageRegistry extends IntegrationTestBase {

    private static final File DIR_REGISTRY_HOME = new File("target/registry");

    private static final Logger log = LoggerFactory.getLogger(TestFSPackageRegistry.class);

    public static final String[] APPLICATION_PATHS = {
            "/libs",
            "/libs/foo"
    };
    
    public static final String[] CONTENT_PATHS = {
            "/tmp",
            "/tmp/foo"
    };
    
    private FSPackageRegistry registry;
    private File registryHome;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        if (DIR_REGISTRY_HOME.exists()) {
            FileUtils.cleanDirectory(DIR_REGISTRY_HOME);
        } else {
            DIR_REGISTRY_HOME.mkdir();
        }
        
        getFreshRegistry();
    }
    
    /**
     * checks is a non existent package is really not there
     */
    @Test
    public void testOpenNonExistentPackage() throws IOException, PackageException {
        assertFalse("package must not exist", registry.contains(TMP_PACKAGE_ID));
        assertNull("package must not exist", registry.open(TMP_PACKAGE_ID));
    }

    /**
     * registers a package via stream
     */
    @Test
    public void testRegisterStream() throws IOException, PackageException {
        PackageId id = registry.register(getStream("testpackages/tmp.zip"), false);
        assertEquals("package id", TMP_PACKAGE_ID, id);

        try (RegisteredPackage pkg = registry.open(id)) {
            assertEquals("package id of registered is correct", TMP_PACKAGE_ID, pkg.getId());
            assertFalse("Package is not installed", pkg.isInstalled());
        }
    }

    /**
     * registers a package twice via stream (replace = false)
     */
    @Test
    public void testRegisterStreamTwiceFails() throws IOException, PackageException {
        PackageId id = registry.register(getStream("testpackages/tmp.zip"), false);
        assertEquals("package id", TMP_PACKAGE_ID, id);

        try {
            registry.register(getStream("testpackages/tmp.zip"), false);
            fail("registering the package twice should fail");
        } catch (PackageExistsException e) {
            // expected
            assertEquals("colliding pid must be correct", id, e.getId());
        }
    }

    /**
     * registers a package twice via stream (replace = true)
     */
    @Test
    public void testRegisterStreamTwiceSucceeds() throws IOException, PackageException {
        PackageId id = registry.register(getStream("testpackages/tmp.zip"), false);
        assertEquals("package id", TMP_PACKAGE_ID, id);
        registry.register(getStream("testpackages/tmp.zip"), true);
    }

    /**
     * registers a package twice via a file
     */
    @Test
    public void testRegisterFileTwiceFails() throws IOException, PackageException {
        File file = getTempFile("testpackages/tmp.zip");
        PackageId id = registry.register(file, false);
        assertEquals("package id", TMP_PACKAGE_ID, id);
        assertTrue("file should still exist", file.exists());

        try (RegisteredPackage pkg = registry.open(id)) {
            assertEquals("package id of registered is correct", TMP_PACKAGE_ID, pkg.getId());
            assertFalse("Package is not installed", pkg.isInstalled());
        }

        try {
            registry.register(file, false);
            fail("registering the package twice should fail");
        } catch (PackageExistsException e) {
            // expected
            assertEquals("colliding pid must be correct", id, e.getId());
        } finally {
            file.delete();
        }
    }

    /**
     * registers a package twice via a temp file file
     */
    @Test
    public void testRegisterTempFileTwiceFails() throws IOException, PackageException {
        File file = getTempFile("testpackages/tmp.zip");
        PackageId id = registry.register(file, false);
        assertEquals("package id", TMP_PACKAGE_ID, id);

        try (RegisteredPackage pkg = registry.open(id)) {
            assertEquals("package id of registered is correct", TMP_PACKAGE_ID, pkg.getId());
            assertFalse("Package is not installed", pkg.isInstalled());
        }

        file = getTempFile("testpackages/tmp.zip");
        try {
            registry.register(file, false);
            fail("registering the package twice should fail");
        } catch (PackageExistsException e) {
            // expected
            assertEquals("colliding pid must be correct", id, e.getId());
        }
    }

    /**
     * registers a package twice via file (replace = true)
     */
    @Test
    public void testRegisterFileTwiceSucceeds() throws IOException, PackageException {
        File file = getTempFile("testpackages/tmp.zip");
        PackageId id = registry.register(file, false);
        assertEquals("package id", TMP_PACKAGE_ID, id);
        assertTrue("file should still exist", file.exists());
        registry.register(file, true);
        file.delete();
    }
    
    /**
     * registers a file as external package twice (replace = false)
     */
    @Test
    public void testRegisterExternalFileTwiceFails() throws IOException, PackageException {
        File file = getTempFile("testpackages/tmp.zip");
        PackageId id = registry.registerExternal(file, false);
        assertEquals("package id", TMP_PACKAGE_ID, id);

        try (RegisteredPackage pkg = registry.open(id)) {
            assertEquals("package id of registered is correct", TMP_PACKAGE_ID, pkg.getId());
            assertFalse("Package is not installed", pkg.isInstalled());
        }

        file = getTempFile("testpackages/tmp.zip");
        try {
            registry.registerExternal(file, false);
            fail("registering the package twice should fail");
        } catch (PackageExistsException e) {
            // expected
            assertEquals("colliding pid must be correct", id, e.getId());
        }
    }
    
    /**
     * registers a file as external package twice with 
     */
    @Test
    public void testRegisterExternalFileTwiceFailsLoadedRegistry() throws IOException, PackageException {
        File file = getTempFile("testpackages/tmp.zip");
        PackageId id = registry.registerExternal(file, false);
        assertEquals("package id", TMP_PACKAGE_ID, id);

        try (RegisteredPackage pkg = registry.open(id)) {
            assertEquals("package id of registered is correct", TMP_PACKAGE_ID, pkg.getId());
            assertFalse("Package is not installed", pkg.isInstalled());
        }
        
        // loading registry again to force loading of metadata from files
        registry = new FSPackageRegistry(registryHome);
        
        try {
            registry.registerExternal(file, false);
            fail("registering the package twice should fail");
        } catch (PackageExistsException e) {
            // expected
            assertEquals("colliding pid must be correct", id, e.getId());
        }
    }


    /**
     * registers a file as external package twice (replace = false)
     */
    @Test
    public void testRegisterExternalFileTwiceSucceeds() throws IOException, PackageException {
        File file = getTempFile("testpackages/tmp.zip");
        PackageId id = registry.registerExternal(file, false);
        assertEquals("package id", TMP_PACKAGE_ID, id);
        assertTrue("file should still exist", file.exists());
        registry.registerExternal(file, true);
        file.delete();
    }
    
    /**
     * registers a file as external package with subpackages (replace = true)
     */
    @Test
    public void testRegisterExternalWithSubPackages() throws IOException, PackageException {
        File file = getTempFile("testpackages/subtest.zip");
        registry.registerExternal(file, false);

        assertTrue(registry.contains(PACKAGE_ID_SUB_A));
        assertTrue(registry.contains(PACKAGE_ID_SUB_B));
    }
    
    /**
     * installs a file as external package with subpackages 
     * Subpackages are only installed if either explicitly added to executionPlan or another package depends on them.
     */
    @Test
    public void testInstallExternalWithSubPackages() throws IOException, PackageException {
        File file = getTempFile("testpackages/subtest.zip");
        PackageId parentPkg = registry.registerExternal(file, false);
        
        ExecutionPlanBuilder builder = registry.createExecutionPlan();
        builder.with(new ProgressTrackerListener() {
            public void onMessage(Mode mode, String action, String path) {
                log.info("{} {}", action, path);
            }

            public void onError(Mode mode, String path, Exception e) {
                log.info("E {} {}", path, e.toString());
            }
        });
        builder.addTask().with(parentPkg).with(Type.EXTRACT);
        ExecutionPlan plan  = builder.with(admin).execute();
        assertFalse(plan.hasErrors());
        
        assertFalse(registry.open(PACKAGE_ID_SUB_A).isInstalled());
        assertFalse(registry.open(PACKAGE_ID_SUB_B).isInstalled());
    }
    
    


    @SuppressWarnings("deprecation")
    @Test
    public void testInstallExternalUnScoped() throws IOException, PackageException, RepositoryException, org.apache.jackrabbit.oak.plugins.segment.file.InvalidFileStoreVersionException {
        File file = getTempFile("testpackages/mixed_package.zip");
        
        cleanPaths(APPLICATION_PATHS);
        cleanPaths(CONTENT_PATHS);
        getFreshRegistry();

        PackageId pkg = registry.registerExternal(file, false);
        
        ExecutionPlanBuilder builder = registry.createExecutionPlan();
        Collector listener = new Collector();
        builder.with(listener);
        builder.addTask().with(pkg).with(Type.EXTRACT);
        ExecutionPlan plan  = builder.with(admin).execute();
        assertFalse(plan.hasErrors());
        checkFiltered(APPLICATION_PATHS, new String[] {}, listener.paths);
        checkFiltered(CONTENT_PATHS, new String[] {}, listener.paths);
    }

    @SuppressWarnings("deprecation")
    @Test
    public void testInstallExternalContentScoped() throws IOException, PackageException, RepositoryException, org.apache.jackrabbit.oak.plugins.segment.file.InvalidFileStoreVersionException {
        File file = getTempFile("testpackages/mixed_package.zip");

        cleanPaths(APPLICATION_PATHS);
        cleanPaths(CONTENT_PATHS);
        getFreshRegistry(InstallationScope.CONTENT_SCOPED);
        
        PackageId pkg = registry.registerExternal(file, false);
        
        ExecutionPlanBuilder builder = registry.createExecutionPlan();
        Collector listener = new Collector();
        builder.with(listener);
        builder.addTask().with(pkg).with(Type.EXTRACT);
        ExecutionPlan plan  = builder.with(admin).execute();
        assertFalse(plan.hasErrors());
        checkFiltered(CONTENT_PATHS, APPLICATION_PATHS, listener.paths);
    }

    @SuppressWarnings("deprecation")
    private void cleanPaths(String[] paths) throws IOException, RepositoryException, org.apache.jackrabbit.oak.plugins.segment.file.InvalidFileStoreVersionException  {
        for (String path : paths) {
            clean(path);
        }
    }

    @SuppressWarnings("deprecation")
    @Test
    public void testInstallExternalApplicationScoped() throws IOException, PackageException, RepositoryException, org.apache.jackrabbit.oak.plugins.segment.file.InvalidFileStoreVersionException {
        File file = getTempFile("testpackages/mixed_package.zip");
        
        cleanPaths(APPLICATION_PATHS);
        cleanPaths(CONTENT_PATHS);
        getFreshRegistry(InstallationScope.APPLICATION_SCOPED);
        
        PackageId pkg = registry.registerExternal(file, false);
        
        ExecutionPlanBuilder builder = registry.createExecutionPlan();
        Collector listener = new Collector();
        builder.with(listener);
        builder.addTask().with(pkg).with(Type.EXTRACT);
        ExecutionPlan plan  = builder.with(admin).execute();
        assertFalse(plan.hasErrors());
        checkFiltered(APPLICATION_PATHS, CONTENT_PATHS, listener.paths);
        
    }
    

    /**
     * test if package removal works
     */
    @Test
    public void testRemovePackage() throws IOException, PackageException {
        PackageId id = registry.register(getStream("testpackages/tmp.zip"), false);
        assertEquals("package id", TMP_PACKAGE_ID, id);

        registry.remove(id);
        assertFalse("package must not exist", registry.contains(TMP_PACKAGE_ID));
        assertNull("package must not exist", registry.open(TMP_PACKAGE_ID));
    }

    /**
     * test packages set
     */
    @Test
    public void testPackages() throws IOException, PackageException {
        assertTrue("initially the packages set is empty", registry.packages().isEmpty());
        registry.register(getStream("testpackages/tmp.zip"), false);
        assertEquals("packages contains 1 element", 1, registry.packages().size());
        assertTrue("contains new package", registry.packages().contains(TMP_PACKAGE_ID));
    }

    /**
     * test if remove non existing should fail
     */
    @Test
    public void testRemoveNonExistingPackage() throws IOException, PackageException {
        try {
            registry.remove(TMP_PACKAGE_ID);
            fail("remove non existing should fail");
        } catch (NoSuchPackageException e) {
            assertEquals("exception should contain correct package id", TMP_PACKAGE_ID, e.getId());
        }
    }

    /**
     * test if analyze dependencies fails for non existing package
     */
    @Test
    public void testAnalyzeDependenciesFailsForNonExisting() throws IOException {
        try {
            registry.analyzeDependencies(TMP_PACKAGE_ID, false);
            fail("usage report should fail for non existing package.");
        } catch (NoSuchPackageException e) {
            assertEquals("exception should contain correct package id", TMP_PACKAGE_ID, e.getId());
        }
    }

    /**
     * test if analyze dependencies is correct for non installed packages
     */
    @Test
    public void testAnalyzeDependencies() throws IOException, PackageException {
        // a depends on b and c
        PackageId idA = registry.register(getStream(TEST_PACKAGE_A_10), false);

        DependencyReport report = registry.analyzeDependencies(idA, false);
        assertEquals("resolved dependencies", "", PackageId.toString(report.getResolvedDependencies()));
        assertEquals("unresolved dependencies", "my_packages:test_b,my_packages:test_c:[1.0,2.0)",
                Dependency.toString(report.getUnresolvedDependencies()));

        // b depends on c
        registry.register(getStream(TEST_PACKAGE_B_10), false);
        report = registry.analyzeDependencies(idA, false);
        assertEquals("resolved dependencies", "my_packages:test_b:1.0",
                PackageId.toString(report.getResolvedDependencies()));
        assertEquals("unresolved dependencies", "my_packages:test_c:[1.0,2.0)",
                Dependency.toString(report.getUnresolvedDependencies()));

        registry.register(getStream(TEST_PACKAGE_C_10), false);
        report = registry.analyzeDependencies(idA, false);
        assertEquals("resolved dependencies", "my_packages:test_b:1.0,my_packages:test_c:1.0",
                PackageId.toString(report.getResolvedDependencies()));
        assertEquals("unresolved dependencies", "", Dependency.toString(report.getUnresolvedDependencies()));

    }

    @Test
    public void testUnsupportedInstallTasks() throws IOException, PackageException, RepositoryException {
        // a depends on b and c
        PackageId idC = registry.register(getStream(TEST_PACKAGE_C_10), false);

        ExecutionPlanBuilder builder = registry.createExecutionPlan();
        builder.with(new ProgressTrackerListener() {
            public void onMessage(Mode mode, String action, String path) {
                log.info("{} {}", action, path);
            }

            public void onError(Mode mode, String path, Exception e) {
                log.info("E {} {}", path, e.toString());
            }
        });

        builder.addTask().with(idC).with(PackageTask.Type.INSTALL);
        ExecutionPlan plan  = builder.with(admin).execute();
        assertTrue(plan.hasErrors());
        assertFalse(registry.open(idC).isInstalled());
    }

    @Test
    public void testExecutionPlanInstallation() throws IOException, PackageException, RepositoryException {
        // a depends on b and c
        PackageId idA = registry.register(getStream(TEST_PACKAGE_A_10), false);

        DependencyReport report = registry.analyzeDependencies(idA, false);
        assertEquals("resolved dependencies", "", PackageId.toString(report.getResolvedDependencies()));
        assertEquals("unresolved dependencies", "my_packages:test_b,my_packages:test_c:[1.0,2.0)",
                Dependency.toString(report.getUnresolvedDependencies()));

        // b depends on c
        PackageId idB = registry.register(getStream(TEST_PACKAGE_B_10), false);
        report = registry.analyzeDependencies(idB, false);
        assertEquals("resolved dependencies", "", PackageId.toString(report.getResolvedDependencies()));
        assertEquals("unresolved dependencies", "my_packages:test_c",
                Dependency.toString(report.getUnresolvedDependencies()));

        ExecutionPlanBuilder builder = registry.createExecutionPlan();
        builder.with(new ProgressTrackerListener() {
            public void onMessage(Mode mode, String action, String path) {
                log.info("{} {}", action, path);
            }

            public void onError(Mode mode, String path, Exception e) {
                log.info("E {} {}", path, e.toString());
            }
        });

        builder.addTask().with(idA).with(PackageTask.Type.EXTRACT);
        builder.addTask().with(idB).with(PackageTask.Type.EXTRACT);
        try {
            builder.with(admin).execute();
            fail("registering the package with missing dependencies should fail");
        } catch (DependencyException ex) {
            // expected
        }
        PackageId idC = registry.register(getStream(TEST_PACKAGE_C_10), false);
        report = registry.analyzeDependencies(idB, false);
        assertEquals("resolved dependencies", "my_packages:test_c:1.0",
                PackageId.toString(report.getResolvedDependencies()));
        assertEquals("unresolved dependencies", "", Dependency.toString(report.getUnresolvedDependencies()));

        builder.addTask().with(idC).with(PackageTask.Type.EXTRACT);
        ExecutionPlan plan  = builder.with(admin).execute();
        assertFalse(plan.hasErrors());

        assertTrue(registry.open(idA).isInstalled());
        assertTrue(registry.open(idB).isInstalled());
        assertTrue(registry.open(idC).isInstalled());
    }
    
    @Test
    public void testExtractSubPackage() throws IOException, PackageException, RepositoryException {
        registry.register(getStream("testpackages/subtest.zip"), false);

        assertTrue(registry.contains(PACKAGE_ID_SUB_A));
        assertTrue(registry.contains(PACKAGE_ID_SUB_B));
    }

    @Test
    public void testUsages() throws Exception {
        PackageId idB = registry.register(getStream(TEST_PACKAGE_B_10), false);
        PackageId idC = registry.register(getStream(TEST_PACKAGE_C_10), false);

        assertEquals("usage", "", PackageId.toString(registry.usage(idC)));

        ExecutionPlanBuilder builder = registry.createExecutionPlan();
        builder.with(new ProgressTrackerListener() {
            public void onMessage(Mode mode, String action, String path) {
                log.info("{} {}", action, path);
            }

            public void onError(Mode mode, String path, Exception e) {
                log.info("E {} {}", path, e.toString());
            }
        });

        builder.addTask().with(idB).with(PackageTask.Type.EXTRACT);
        builder.addTask().with(idC).with(PackageTask.Type.EXTRACT);
        ExecutionPlan plan  = builder.with(admin).execute();
        assertFalse(plan.hasErrors());

        assertEquals("usage", "my_packages:test_b:1.0", PackageId.toString(registry.usage(idC)));
    }
    
    @Test
    public void testInstalledDependencies() throws Exception {
        PackageId idB = registry.register(getStream(TEST_PACKAGE_B_10), false);
        PackageId idC = registry.register(getStream(TEST_PACKAGE_C_10), false);

        assertEquals("usage", "", PackageId.toString(registry.usage(idC)));

        ExecutionPlanBuilder builder = registry.createExecutionPlan();
        builder.with(new ProgressTrackerListener() {
            public void onMessage(Mode mode, String action, String path) {
                log.info("{} {}", action, path);
            }

            public void onError(Mode mode, String path, Exception e) {
                log.info("E {} {}", path, e.toString());
            }
        });

        builder.addTask().with(idC).with(PackageTask.Type.EXTRACT);
        ExecutionPlan plan  = builder.with(admin).execute();
        assertFalse(plan.hasErrors());

        Dependency depB = new Dependency(idB);
        Dependency depC = new Dependency(idC);
        assertNull("Dependency B should not resolve", registry.resolve(depB, true));
        assertEquals("Dependency C should resovle to package C", idC, registry.resolve(depC, true));
    }
    
    
    @Test
    public void testInstallTime() throws Exception {

        PackageId idC = registry.register(getStream(TEST_PACKAGE_C_10), false);

        assertNull(registry.open(idC).getInstallationTime());
        
        ExecutionPlanBuilder builder = registry.createExecutionPlan();
        builder.with(new ProgressTrackerListener() {
            public void onMessage(Mode mode, String action, String path) {
                log.info("{} {}", action, path);
            }

            public void onError(Mode mode, String path, Exception e) {
                log.info("E {} {}", path, e.toString());
            }
        });

        builder.addTask().with(idC).with(PackageTask.Type.EXTRACT);
        Calendar before = Calendar.getInstance();
        ExecutionPlan plan = builder.with(admin).execute();
        Calendar after = Calendar.getInstance();
        assertFalse(plan.hasErrors());

        assertTrue("Installation time for idC too late", registry.open(idC).getInstallationTime().compareTo(after) <= 0);
        assertTrue("Installation time for idC too early", registry.open(idC).getInstallationTime().compareTo(before) >= 0);

    }
    
    @Test
    public void testUnsupportedUninstall() throws Exception {
        PackageId idC = registry.register(getStream(TEST_PACKAGE_C_10), false);

        assertNull(registry.open(idC).getInstallationTime());
        
        ExecutionPlanBuilder builder = registry.createExecutionPlan();
        builder.with(new ProgressTrackerListener() {
            public void onMessage(Mode mode, String action, String path) {
                log.info("{} {}", action, path);
            }

            public void onError(Mode mode, String path, Exception e) {
                log.info("E {} {}", path, e.toString());
            }
        });

        builder.addTask().with(idC).with(PackageTask.Type.EXTRACT);
        ExecutionPlan plan = builder.with(admin).execute();
        assertFalse(plan.hasErrors());

        try{
            registry.uninstallPackage(admin, registry.open(idC), new ImportOptions());
            fail("uninstall attempt should fail.");
        } catch (PackageException ex) {
            //expected
        }
    }
    
    @Test
    public void testNonMetaXmlFile() throws Exception {
        PackageId idC = registry.register(getStream(TEST_PACKAGE_C_10), false);

        assertEquals(idC, registry.getInstallState(idC).getPackageId());
        assertEquals(FSPackageStatus.REGISTERED, registry.getInstallState(idC).getStatus());
        
        Field stateCache = registry.getClass().getDeclaredField("stateCache");
        stateCache.setAccessible(true);
        stateCache.set(registry, new HashMap<String, FSInstallState>()  );
        Method getPackageMetaDataFile = registry.getClass().getDeclaredMethod("getPackageMetaDataFile", new Class<?>[]{idC.getClass()});
        getPackageMetaDataFile.setAccessible(true);
        Method loadPackageCache = registry.getClass().getDeclaredMethod("loadPackageCache");
        loadPackageCache.setAccessible(true);
        File metaFile = (File)getPackageMetaDataFile.invoke(registry, idC);
        FileUtils.copyToFile(getStream("repository.xml"), metaFile);
        loadPackageCache.invoke(registry);
        assertEquals(FSPackageStatus.NOTREGISTERED, registry.getInstallState(idC).getStatus());
    }
    
    private void getFreshRegistry(InstallationScope... scope) throws IOException {
        if (this.registryHome != null && this.registryHome.exists()) {
            this.registryHome.delete();
        }
        this.registryHome = new File(DIR_REGISTRY_HOME, UUID.randomUUID().toString());
        this.registryHome.mkdir();
        if (scope.length > 0) {
            this.registry = new FSPackageRegistry(registryHome, scope[0]);
        } else {
            this.registry = new FSPackageRegistry(registryHome);
        }
    }
    
    private static class Collector implements ProgressTrackerListener {
        private final List<String> paths = new LinkedList<String>();

        public void onMessage(Mode mode, String action, String path) {
            paths.add(path);
        }

        public void onError(Mode mode, String path, Exception e) {
        }
    }
    
    public static void checkFiltered(String[] containing, String[] filtered, List<String> result) {
        assertEquals("Results don't contain expected values", Collections.EMPTY_LIST, CollectionUtils.subtract(Arrays.asList(containing), result));
        assertEquals("Results contain unexpected values", Collections.EMPTY_LIST , CollectionUtils.intersection(result, Arrays.asList(filtered)));
    }

}