/*
 * 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.commons.jci2;

import junit.framework.TestCase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.commons.jci2.classes.SimpleDump;
import org.apache.commons.jci2.stores.ResourceStore;
import org.apache.commons.jci2.stores.MemoryResourceStore;

/**
 * Test ReloadingClassLoader's <code>removeResourceStore({@link ResourceStore})</code>
 * method.
 */
public class ReloadingClassLoaderRemoveTestCase extends TestCase {

    private final Log log = LogFactory.getLog(ReloadingClassLoaderRemoveTestCase.class);

    private final byte[] clazzSimpleA;
    private final MemoryResourceStore store1 = new MemoryResourceStore();
    private final MemoryResourceStore store2 = new MemoryResourceStore();
    private final MemoryResourceStore store3 = new MemoryResourceStore();
    private final MemoryResourceStore store4 = new MemoryResourceStore();

    public ReloadingClassLoaderRemoveTestCase() throws Exception {
        clazzSimpleA = SimpleDump.dump("SimpleA");
        assertTrue(clazzSimpleA.length > 0);
    }

    @Override
    protected void setUp() throws Exception {
        System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
    }

    @Override
    protected void tearDown() throws Exception {
    }

    /**
     * Test trying to remove a ResourceStore from the ReloadingClassLoader
     * which can't be found - when the ClassLoader contains NO other ResourceStore.
     *
     * Bug: The While loop in the removeResourceStore() throws an ArrayOutOfBoundsException
     */
    public void testRemoveStoreNotFoundClassLoaderNoStores() {
        final ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
        checkRemoveResourceStore("No ResourceStore", loader, store1, false);
    }

    /**
     * Test trying to remove a ResourceStore from the ReloadingClassLoader
     * which can't be found - when the ClassLoader DOES contain other ResourceStore.
     *
     * Bug: The While loop in the removeResourceStore() throws an ArrayOutOfBoundsException
     */
    public void testRemoveStoreNotFoundClassLoaderHasStores() {
        final ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
        loader.addResourceStore(store1);
        loader.addResourceStore(store2);
        checkRemoveResourceStore("Has ResourceStore", loader, store3, false);
    }

    /**
     * Test trying to remove the first ResourceStore added
     *
     * Bug: ReloadingClassLoader addes ResourceStore at the start of the array. Removing the
     *      first one added (last in array) causes the second System.arraycopy() statement to throw a
     *      ArrayIndexOutOfBoundsException because the destination array position in the new smaller
     *      array is too large.
     */
    public void testRemoveStoresOne() {
        final ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
        loader.addResourceStore(store1);
        loader.addResourceStore(store2);
        loader.addResourceStore(store3);
        loader.addResourceStore(store4);

        checkRemoveResourceStore("One: Remove Store 1", loader, store1, true);
        checkRemoveResourceStore("One: Store 1 Not Found", loader, store1, false);

        checkRemoveResourceStore("One: Remove Store 2", loader, store2, true);
        checkRemoveResourceStore("One: Store 2 Not Found", loader, store2, false);

        checkRemoveResourceStore("One: Remove Store 3", loader, store3, true);
        checkRemoveResourceStore("One: Store 3 Not Found", loader, store3, false);

        checkRemoveResourceStore("One: Remove Store 4", loader, store4, true);
        checkRemoveResourceStore("One: Store 4 Not Found", loader, store4, false);
    }

    /**
     * Test trying to remove the second ResourceStore added
     *
     * Bug: ReloadingClassLoader addes ResourceStore at the start of the array. Removing the
     *      first one added (last in array) causes the second System.arraycopy() statement to throw a
     *      ArrayIndexOutOfBoundsException (??not sure why??)
     */
    public void testRemoveStoresTwo() {
        final ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
        loader.addResourceStore(store1);
        loader.addResourceStore(store2);
        loader.addResourceStore(store3);
        loader.addResourceStore(store4);

        checkRemoveResourceStore("Two: Remove Store 2", loader, store2, true);
        checkRemoveResourceStore("Two: Store 2 Not Found", loader, store2, false);

        checkRemoveResourceStore("Two: Remove Store 4", loader, store4, true);
        checkRemoveResourceStore("Two: Store 4 Not Found", loader, store4, false);

        checkRemoveResourceStore("Two: Remove Store 3", loader, store3, true);
        checkRemoveResourceStore("Two: Store 3 Not Found", loader, store3, false);

        checkRemoveResourceStore("Two: Remove Store 1", loader, store1, true);
        checkRemoveResourceStore("Two: Store 1 Not Found", loader, store1, false);
    }

    /**
     * Test trying to remove the third ResourceStore added
     *
     * Bug: In this scenario the two System.arraycopy() statements don't copy the correct
     *      ResourceStore - it creates a new array where the first resource store is null
     *      and copies store3 and store2 to their same positions
     */
    public void testRemoveStoresThree() {
        final ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
        loader.addResourceStore(store1);
        loader.addResourceStore(store2);
        loader.addResourceStore(store3);
        loader.addResourceStore(store4);

        checkRemoveResourceStore("Three: Remove Store 3", loader, store3, true);
        checkRemoveResourceStore("Three: Store 3 Not Found", loader, store3, false);

        checkRemoveResourceStore("Three: Remove Store 1", loader, store1, true);
        checkRemoveResourceStore("Three: Store 1 Not Found", loader, store1, false);

        checkRemoveResourceStore("Three: Remove Store 4", loader, store4, true);
        checkRemoveResourceStore("Three: Store 4 Not Found", loader, store4, false);

        checkRemoveResourceStore("Three: Remove Store 2", loader, store2, true);
        checkRemoveResourceStore("Three: Store 2 Not Found", loader, store2, false);
    }

    /**
     * Test trying to remove the fourth ResourceStore added
     *
     * Bug: ReloadingClassLoader addes ResourceStore at the start of the array. Removing the
     *      last one added (first in array) causes the first System.arraycopy() statement to throw a
     *      ArrayIndexOutOfBoundsException because the length to copy is -1
     */
    public void testRemoveStoresFour() {
        final ReloadingClassLoader loader = new ReloadingClassLoader(getClass().getClassLoader());
        loader.addResourceStore(store1);
        loader.addResourceStore(store2);
        loader.addResourceStore(store3);
        loader.addResourceStore(store4);

        checkRemoveResourceStore("Four: Remove Store 4", loader, store4, true);
        checkRemoveResourceStore("Four: Store 4 Not Found", loader, store4, false);

        checkRemoveResourceStore("Four: Remove Store 3", loader, store3, true);
        checkRemoveResourceStore("Four: Store 3 Not Found", loader, store3, false);

        checkRemoveResourceStore("Four: Remove Store 2", loader, store2, true);
        checkRemoveResourceStore("Four: Store 2 Not Found", loader, store2, false);

        checkRemoveResourceStore("Four: Remove Store 1", loader, store1, true);
        checkRemoveResourceStore("Four: Store 1 Not Found", loader, store1, false);
    }


    /**
     * Test that a class can't be loaded after the ResourceStore containing
     * it has been removed.
     *
     * Bug: When theres a single ResourceStore in the ClassLoader and its removed
     *      a new "delegate" ClassLoader with the new ResourceStore array isn't being
     *      created - which means that calling loadClass() still returns the classes
     *      from the removed ResourceStore rather than throwing a ClassNotFoundException
     */
    public void testLoadClassAfterResourceStoreRemoved() {

        // Create a class loader & add resource store
        final ReloadingClassLoader loader = new ReloadingClassLoader(this.getClass().getClassLoader());
        final MemoryResourceStore store = new MemoryResourceStore();
        loader.addResourceStore(store);

        // Check "jci2.Simple" class can't be loaded
        try {
            loader.loadClass("jci2.Simple").newInstance();
            fail("Success loadClass[1]");
        } catch(final ClassNotFoundException e) {
            // expected not found
        } catch(final Exception e) {
            log.error(e);
            fail("Error loadClass[1]: " + e);
        }

        // Add "jci2.Simple" class to the resource store
        final String toStringValue = "FooBar";
        try {
            final byte[] classBytes = SimpleDump.dump(toStringValue);
            store.write("jci2/Simple.class", classBytes);
        } catch(final Exception e) {
            log.error(e);
            fail("Error adding class to store: " + e);
        }

        // Check "jci2.Simple" class can now be loaded
        try {
            final Object simple2 = loader.loadClass("jci2.Simple").newInstance();
            assertNotNull("Found loadClass[2]",  simple2);
            assertEquals("toString loadClass[2]",  toStringValue, simple2.toString());
        } catch(final Exception e) {
            log.error(e);
            fail("Error loadClass[2]: " + e);
        }

        // Remove the resource store from the class loader
        checkRemoveResourceStore("Remove Resource Store", loader, store, true);

        // Test "jci2.Simple" class can't be loaded after ResourceStore removed
        try {
            loader.loadClass("jci2.Simple").newInstance();
            fail("Success loadClass[3]");
        } catch(final ClassNotFoundException e) {
            // expected not found
        } catch(final Exception e) {
            log.error(e);
            fail("Error loadClass[3]: " + e);
        }

    }

    /**
     * Check removing a ResourceStore from ReloadingClassLoader
     */
    private void checkRemoveResourceStore(final String label, final ReloadingClassLoader loader, final ResourceStore store, final boolean expected) {
        try {
            assertEquals(label, expected, loader.removeResourceStore(store));
        } catch(final Exception e) {
            log.error(label, e);
            fail(label + " failed: " + e);
        }
    }
}
