/*
 * 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.felix.framework;

import org.apache.felix.framework.BundleWiringImpl.BundleClassLoader;
import org.apache.felix.framework.cache.Content;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.hooks.weaving.WeavingException;
import org.osgi.framework.hooks.weaving.WeavingHook;
import org.osgi.framework.hooks.weaving.WovenClass;
import org.osgi.framework.hooks.weaving.WovenClassListener;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class BundleWiringImplTest
{

    private BundleWiringImpl bundleWiring;

    private StatefulResolver mockResolver;

    private BundleRevisionImpl mockRevisionImpl;

    private BundleImpl mockBundle;

    @SuppressWarnings("rawtypes")
    public void initializeSimpleBundleWiring() throws Exception
    {

        mockResolver = mock(StatefulResolver.class);
        mockRevisionImpl = mock(BundleRevisionImpl.class);
        mockBundle = mock(BundleImpl.class);

        Logger logger = new Logger();
        Map configMap = new HashMap();
        List<BundleRevision> fragments = new ArrayList<BundleRevision>();
        List<BundleWire> wires = new ArrayList<BundleWire>();
        Map<String, BundleRevision> importedPkgs = new HashMap<String, BundleRevision>();
        Map<String, List<BundleRevision>> requiredPkgs = new HashMap<String, List<BundleRevision>>();

        when(mockRevisionImpl.getBundle()).thenReturn(mockBundle);
        when(mockBundle.getBundleId()).thenReturn(Long.valueOf(1));

        bundleWiring = new BundleWiringImpl(logger, configMap, mockResolver,
                mockRevisionImpl, fragments, wires, importedPkgs, requiredPkgs);
    }

    @Test
    public void testBundleClassLoader() throws Exception
    {
        bundleWiring = mock(BundleWiringImpl.class);
        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);
    }

    @SuppressWarnings("rawtypes")
    @Test
    public void testFindClassNonExistant() throws Exception
    {
        initializeSimpleBundleWiring();

        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);
        Class foundClass = null;
        try
        {
            foundClass = bundleClassLoader
                    .findClass("org.apache.felix.test.NonExistant");
        } catch (ClassNotFoundException e)
        {
            fail("Class should not throw exception");
        }
        assertNull("Nonexistant Class Should be null", foundClass);
    }

    @SuppressWarnings("rawtypes")
    @Test
    public void testFindClassExistant() throws Exception
    {
        Felix mockFramework = mock(Felix.class);
        HookRegistry hReg = mock(HookRegistry.class);
        Mockito.when(mockFramework.getHookRegistry()).thenReturn(hReg);
        Content mockContent = mock(Content.class);
        Class testClass = TestClass.class;
        String testClassName = testClass.getName();
        String testClassAsPath = testClassName.replace('.', '/') + ".class";
        byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);

        List<Content> contentPath = new ArrayList<Content>();
        contentPath.add(mockContent);
        initializeSimpleBundleWiring();

        when(mockBundle.getFramework()).thenReturn(mockFramework);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
        when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(
                testClassBytes);

        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);
        Class foundClass = null;
        try
        {

            foundClass = bundleClassLoader.findClass(TestClass.class.getName());
        } catch (ClassNotFoundException e)
        {
            fail("Class should not throw exception");
        }
        assertNotNull("Class Should be found in this classloader", foundClass);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Test
    public void testFindClassWeave() throws Exception
    {
        Felix mockFramework = mock(Felix.class);
        Content mockContent = mock(Content.class);
        ServiceReference<WeavingHook> mockServiceReferenceWeavingHook = mock(ServiceReference.class);
        ServiceReference<WovenClassListener> mockServiceReferenceWovenClassListener = mock(ServiceReference.class);

        Set<ServiceReference<WeavingHook>> hooks = new HashSet<ServiceReference<WeavingHook>>();
        hooks.add(mockServiceReferenceWeavingHook);

        DummyWovenClassListener dummyWovenClassListener = new DummyWovenClassListener();

        Set<ServiceReference<WovenClassListener>> listeners = new HashSet<ServiceReference<WovenClassListener>>();
        listeners.add(mockServiceReferenceWovenClassListener);

        Class testClass = TestClass.class;
        String testClassName = testClass.getName();
        String testClassAsPath = testClassName.replace('.', '/') + ".class";
        byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);

        List<Content> contentPath = new ArrayList<Content>();
        contentPath.add(mockContent);
        initializeSimpleBundleWiring();

        when(mockBundle.getFramework()).thenReturn(mockFramework);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
        when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(
                testClassBytes);

        HookRegistry hReg = mock(HookRegistry.class);
        when(hReg.getHooks(WeavingHook.class)).thenReturn(hooks);
        when(mockFramework.getHookRegistry()).thenReturn(hReg);
        when(
                mockFramework.getService(mockFramework,
                        mockServiceReferenceWeavingHook, false)).thenReturn(
                                new GoodDummyWovenHook());

        when(hReg.getHooks(WovenClassListener.class)).thenReturn(
                listeners);
        when(
                mockFramework.getService(mockFramework,
                        mockServiceReferenceWovenClassListener, false))
        .thenReturn(dummyWovenClassListener);

        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);
        Class foundClass = null;
        try
        {

            foundClass = bundleClassLoader.findClass(TestClass.class.getName());
        } catch (ClassNotFoundException e)
        {
            fail("Class should not throw exception");
        }
        assertNotNull("Class Should be found in this classloader", foundClass);
        assertEquals("Weaving should have added a field", 1,
                foundClass.getFields().length);
        assertEquals("There should be 2 state changes fired by the weaving", 2,
                dummyWovenClassListener.stateList.size());
        assertEquals("The first state change should transform the class",
                (Object)WovenClass.TRANSFORMED,
                dummyWovenClassListener.stateList.get(0));
        assertEquals("The second state change should define the class",
                (Object)WovenClass.DEFINED, dummyWovenClassListener.stateList.get(1));
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Test
    public void testFindClassBadWeave() throws Exception
    {
        Felix mockFramework = mock(Felix.class);
        Content mockContent = mock(Content.class);
        ServiceReference<WeavingHook> mockServiceReferenceWeavingHook = mock(ServiceReference.class);
        ServiceReference<WovenClassListener> mockServiceReferenceWovenClassListener = mock(ServiceReference.class);

        Set<ServiceReference<WeavingHook>> hooks = new HashSet<ServiceReference<WeavingHook>>();
        hooks.add(mockServiceReferenceWeavingHook);

        DummyWovenClassListener dummyWovenClassListener = new DummyWovenClassListener();

        Set<ServiceReference<WovenClassListener>> listeners = new HashSet<ServiceReference<WovenClassListener>>();
        listeners.add(mockServiceReferenceWovenClassListener);

        Class testClass = TestClass.class;
        String testClassName = testClass.getName();
        String testClassAsPath = testClassName.replace('.', '/') + ".class";
        byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);

        List<Content> contentPath = new ArrayList<Content>();
        contentPath.add(mockContent);
        initializeSimpleBundleWiring();

        when(mockBundle.getFramework()).thenReturn(mockFramework);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
        when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(
                testClassBytes);

        HookRegistry hReg = mock(HookRegistry.class);
        when(hReg.getHooks(WeavingHook.class)).thenReturn(hooks);
        when(mockFramework.getHookRegistry()).thenReturn(hReg);
        when(
                mockFramework.getService(mockFramework,
                        mockServiceReferenceWeavingHook, false)).thenReturn(
                                new BadDummyWovenHook());

        when(hReg.getHooks(WovenClassListener.class)).thenReturn(
                listeners);
        when(
                mockFramework.getService(mockFramework,
                        mockServiceReferenceWovenClassListener, false))
        .thenReturn(dummyWovenClassListener);

        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);

        try
        {

            bundleClassLoader.findClass(TestClass.class.getName());
            fail("Class should throw exception");
        } catch (Error e)
        {
            // This is expected
        }

        assertEquals("There should be 1 state changes fired by the weaving", 1,
                dummyWovenClassListener.stateList.size());
        assertEquals(
                "The only state change should be a failed transform on the class",
                (Object)WovenClass.TRANSFORMING_FAILED,
                dummyWovenClassListener.stateList.get(0));

    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Test
    public void testFindClassWeaveDefineError() throws Exception
    {
        Felix mockFramework = mock(Felix.class);
        Content mockContent = mock(Content.class);
        ServiceReference<WeavingHook> mockServiceReferenceWeavingHook = mock(ServiceReference.class);
        ServiceReference<WovenClassListener> mockServiceReferenceWovenClassListener = mock(ServiceReference.class);

        Set<ServiceReference<WeavingHook>> hooks = new HashSet<ServiceReference<WeavingHook>>();
        hooks.add(mockServiceReferenceWeavingHook);

        DummyWovenClassListener dummyWovenClassListener = new DummyWovenClassListener();

        Set<ServiceReference<WovenClassListener>> listeners = new HashSet<ServiceReference<WovenClassListener>>();
        listeners.add(mockServiceReferenceWovenClassListener);

        Class testClass = TestClass.class;
        String testClassName = testClass.getName();
        String testClassAsPath = testClassName.replace('.', '/') + ".class";
        byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);

        List<Content> contentPath = new ArrayList<Content>();
        contentPath.add(mockContent);
        initializeSimpleBundleWiring();

        when(mockBundle.getFramework()).thenReturn(mockFramework);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
        when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(
                testClassBytes);

        HookRegistry hReg = mock(HookRegistry.class);
        when(hReg.getHooks(WeavingHook.class)).thenReturn(hooks);
        when(mockFramework.getHookRegistry()).thenReturn(hReg);
        when(
                mockFramework.getService(mockFramework,
                        mockServiceReferenceWeavingHook, false)).thenReturn(
                                new BadDefineWovenHook());

        when(hReg.getHooks(WovenClassListener.class)).thenReturn(
                listeners);
        when(
                mockFramework.getService(mockFramework,
                        mockServiceReferenceWovenClassListener, false))
        .thenReturn(dummyWovenClassListener);

        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);
        try
        {

            bundleClassLoader.findClass(TestClass.class.getName());
            fail("Class should throw exception");
        } catch (Throwable e)
        {

        }
        assertEquals("There should be 2 state changes fired by the weaving", 2,
                dummyWovenClassListener.stateList.size());
        assertEquals("The first state change should transform the class",
                (Object)WovenClass.TRANSFORMED,
                dummyWovenClassListener.stateList.get(0));
        assertEquals("The second state change failed the define on the class",
                (Object)WovenClass.DEFINE_FAILED,
                dummyWovenClassListener.stateList.get(1));
    }

    private ConcurrentHashMap<String, ClassLoader> getAccessorCache(BundleWiringImpl wiring) throws NoSuchFieldException, IllegalAccessException {
        Field m_accessorLookupCache = BundleWiringImpl.class.getDeclaredField("m_accessorLookupCache");
        m_accessorLookupCache.setAccessible(true);
        return (ConcurrentHashMap<String, ClassLoader>) m_accessorLookupCache.get(wiring);
    }

    @Test
    public void testFirstGeneratedAccessorSkipClassloading() throws Exception
    {

        String classToBeLoaded = "sun.reflect.GeneratedMethodAccessor21";

        Felix mockFramework = mock(Felix.class);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        initializeSimpleBundleWiring();

        when(bundleWiring.getBundle().getFramework()).thenReturn(mockFramework);

        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);

        try {
            bundleClassLoader.loadClass(classToBeLoaded, true);
            fail();
        } catch (ClassNotFoundException cnf) {
            //this is expected

            //make sure boot delegation was done before CNF was thrown
            verify(mockFramework).getBootPackages();

            //make sure the class is added to the skip class cache
            assertEquals(getAccessorCache(bundleWiring).get(classToBeLoaded), BundleWiringImpl.CNFE_CLASS_LOADER);
        } catch (Exception e) {
            e.printStackTrace();
            fail();
        }
    }

    @SuppressWarnings("rawtypes")
    public void initializeBundleWiringWithImportsAndRequired(Map<String, BundleRevision> importedPkgs, Map<String, List<BundleRevision>> requiredPkgs) throws Exception
    {

        mockResolver = mock(StatefulResolver.class);
        mockRevisionImpl = mock(BundleRevisionImpl.class);
        mockBundle = mock(BundleImpl.class);

        Logger logger = new Logger();
        Map configMap = new HashMap();
        List<BundleRevision> fragments = new ArrayList<BundleRevision>();
        List<BundleWire> wires = new ArrayList<BundleWire>();

        when(mockRevisionImpl.getBundle()).thenReturn(mockBundle);
        when(mockBundle.getBundleId()).thenReturn(Long.valueOf(1));

        bundleWiring = new BundleWiringImpl(logger, configMap, mockResolver,
                mockRevisionImpl, fragments, wires, importedPkgs, requiredPkgs);
    }

    @Test
    public void testAccessorFirstLoadFailed() throws Exception
    {

        String classToBeLoaded = "sun.reflect.GeneratedMethodAccessor21";

        Felix mockFramework = mock(Felix.class);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        Map<String, BundleRevision> importedPkgs = mock(Map.class);
        Map<String, List<BundleRevision>> requiredPkgs = mock(Map.class);

        initializeBundleWiringWithImportsAndRequired(importedPkgs, requiredPkgs);

        when(bundleWiring.getBundle().getFramework()).thenReturn(mockFramework);

        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);

        try {
            bundleClassLoader.loadClass(classToBeLoaded, true);
            fail();
        } catch (ClassNotFoundException cnf) {
            //this is expected

            //make sure boot delegation was done before CNF was thrown
            verify(mockFramework).getBootPackages();

            //make sure imported and required pkgs are searched
            verify(importedPkgs).values();
            verify(requiredPkgs).values();

            //make sure the class is added to the skip class cache
            assertEquals(getAccessorCache(bundleWiring).get(classToBeLoaded), BundleWiringImpl.CNFE_CLASS_LOADER);
        } catch (Exception e) {
            e.printStackTrace();
            fail();
        }
    }

    @Test
    public void testAccessorSubsequentLoadFailed() throws Exception
    {

        String classToBeLoaded = "sun.reflect.GeneratedMethodAccessor21";

        Felix mockFramework = mock(Felix.class);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        Map<String, BundleRevision> importedPkgs = mock(Map.class);
        Map<String, List<BundleRevision>> requiredPkgs = mock(Map.class);

        initializeBundleWiringWithImportsAndRequired(importedPkgs, requiredPkgs);

        when(bundleWiring.getBundle().getFramework()).thenReturn(mockFramework);

        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);

        //first attempt to populate the cache
        try {
            bundleClassLoader.loadClass(classToBeLoaded, true);
            fail();
        } catch (ClassNotFoundException cnf) {
            //this is expected
        }

        //now test that the subsequent class load throws CNF with out boot delegation and import/required packages
        try {

            importedPkgs = mock(Map.class);
            requiredPkgs = mock(Map.class);
            initializeBundleWiringWithImportsAndRequired(importedPkgs, requiredPkgs);
            mockFramework = mock(Felix.class);
            when(mockFramework.getBootPackages()).thenReturn(new String[0]);
            when(bundleWiring.getBundle().getFramework()).thenReturn(mockFramework);
            bundleClassLoader.loadClass(classToBeLoaded, true);
            fail();
        } catch (ClassNotFoundException cnf) {
            //this is expected

            //make sure boot delegation was not used
            verify(mockFramework, never()).getBootPackages();

            //make sure boot import and required packages were not searched
            verify(importedPkgs, never()).values();
            verify(requiredPkgs, never()).values();

        } catch (Exception e) {
            e.printStackTrace();
            fail();
        }
    }

    private BundleRevision getBundleRevision(String classToBeLoaded, BundleClassLoader pkgBundleClassLoader, Object value) throws ClassNotFoundException {
        BundleRevision bundleRevision = mock(BundleRevision.class);
        BundleWiring pkgBundleWiring = mock(BundleWiring.class);
        when(pkgBundleClassLoader.findLoadedClassInternal(classToBeLoaded)).thenAnswer(createAnswer(value));
        when(pkgBundleClassLoader.loadClass(classToBeLoaded)).thenAnswer(createAnswer(value));

        when(pkgBundleWiring.getClassLoader()).thenReturn(pkgBundleClassLoader);
        when(bundleRevision.getWiring()).thenReturn(pkgBundleWiring);
        return bundleRevision;
    }

    @Test
    public void testAccessorLoadImportPackage() throws Exception
    {

        String classToBeLoaded = "sun.reflect.GeneratedMethodAccessor21";

        Felix mockFramework = mock(Felix.class);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        Map<String, BundleRevision> importedPkgs = mock(Map.class);
        BundleClassLoader foundClassLoader = mock(BundleClassLoader.class);
        BundleClassLoader notFoundClassLoader = mock(BundleClassLoader.class);
        BundleRevision bundleRevision1 = getBundleRevision(classToBeLoaded, foundClassLoader, String.class);
        BundleRevision bundleRevision2 = getBundleRevision(classToBeLoaded, notFoundClassLoader, null);
        Map<String, BundleRevision> importedPkgsActual = new LinkedHashMap<String, BundleRevision>();
        importedPkgsActual.put("sun.reflect1", bundleRevision1);
        importedPkgsActual.put("sun.reflect2", bundleRevision2);
        when(importedPkgs.values()).thenReturn(importedPkgsActual.values());
        Map<String, List<BundleRevision>> requiredPkgs = mock(Map.class);

        initializeBundleWiringWithImportsAndRequired(importedPkgs, requiredPkgs);

        when(bundleWiring.getBundle().getFramework()).thenReturn(mockFramework);

        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);

        //call class load to populate the cache
        try {
            Object result = bundleClassLoader.loadClass(classToBeLoaded, true);
            assertNotNull(result);
            assertTrue(getAccessorCache(bundleWiring).containsKey(classToBeLoaded));
            assertEquals(getAccessorCache(bundleWiring).get(classToBeLoaded), foundClassLoader);
            verify(foundClassLoader, times(1)).findLoadedClassInternal(classToBeLoaded);
            verify(notFoundClassLoader, never()).findLoadedClassInternal(classToBeLoaded);
        } catch (Exception e) {
            fail();
        }

        //now make sure subsequent class load happens from cached revision
        Object result = bundleClassLoader.loadClass(classToBeLoaded, true);
        assertNotNull(result);
        //makes sure the look up cache is accessed and the class is loaded from cached revision
        verify(foundClassLoader, times(1)).findLoadedClassInternal(classToBeLoaded);
        verify(foundClassLoader, times(1)).loadClass(classToBeLoaded);
        verify(notFoundClassLoader, never()).findLoadedClassInternal(classToBeLoaded);
    }

    private static <T> Answer<T> createAnswer(final T value) {
        Answer<T> dummy = new Answer<T>() {
            @Override
            public T answer(InvocationOnMock invocation) throws Throwable {
                return value;
            }
        };
        return dummy;
    }

    @Test
    public void testAccessorBootDelegate() throws Exception
    {

        String classToBeLoaded = "sun.reflect.GeneratedMethodAccessor21";

        Felix mockFramework = mock(Felix.class);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        Map<String, BundleRevision> importedPkgs = mock(Map.class);
        BundleRevision bundleRevision1 = mock(BundleRevision.class);
        Map<String, BundleRevision> importedPkgsActual = new HashMap<String, BundleRevision>();
        importedPkgsActual.put("sun.reflect1", bundleRevision1);
        when(importedPkgs.values()).thenReturn(importedPkgsActual.values());
        Map<String, List<BundleRevision>> requiredPkgs = mock(Map.class);

        ClassLoader bootDelegateClassLoader = mock(ClassLoader.class);

        when(bootDelegateClassLoader.loadClass(classToBeLoaded)).thenAnswer(createAnswer(String.class));

        initializeBundleWiringWithImportsAndRequired(importedPkgs, requiredPkgs);

        when(bundleWiring.getBundle().getFramework()).thenReturn(mockFramework);

        Field field = bundleWiring.getClass().getDeclaredField("m_bootClassLoader");
        field.setAccessible(true);
        field.set(bundleWiring, bootDelegateClassLoader);

        BundleClassLoader bundleClassLoader = createBundleClassLoader(
                BundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);

        try {
            Object result = bundleClassLoader.loadClass(classToBeLoaded, true);
            assertNotNull(result);
            verify(importedPkgs, never()).values();
            verify(requiredPkgs, never()).values();
            assertTrue(getAccessorCache(bundleWiring).containsKey(classToBeLoaded));
            assertTrue(getAccessorCache(bundleWiring).get(classToBeLoaded) == bootDelegateClassLoader);
        } catch (Exception e) {
            fail();
        }

        //now make sure subsequent class loading happens from boot delegation
        Object result = bundleClassLoader.loadClass(classToBeLoaded, true);
        assertNotNull(result);
        //makes sure the look up cache is accessed and the class is loaded via boot delegation
        verify(importedPkgs, never()).values();
        verify(requiredPkgs, never()).values();
    }

    @Test
    public void testParallelClassload() throws Exception
    {


        Felix mockFramework = mock(Felix.class);
        HookRegistry hReg = mock(HookRegistry.class);
        Mockito.when(mockFramework.getHookRegistry()).thenReturn(hReg);
        Content mockContent = mock(Content.class);
        final Class testClass = TestClassSuper.class;
        final String testClassName = testClass.getName();
        final String testClassAsPath = testClassName.replace('.', '/') + ".class";
        byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);

        final Class testClass2 = TestClassChild.class;
        final String testClassName2 = testClass2.getName();
        final String testClassAsPath2 = testClassName2.replace('.', '/') + ".class";
        byte[] testClassBytes2 = createTestClassBytes(testClass2, testClassAsPath2);

        final Class testClass3 = TestClass.class;
        final String testClassName3 = testClass3.getName();
        final String testClassAsPath3 = testClassName3.replace('.', '/') + ".class";
        byte[] testClassBytes3 = createTestClassBytes(testClass3, testClassAsPath3);

        List<Content> contentPath = new ArrayList<Content>();
        contentPath.add(mockContent);
        BundleWiringImpl bundleWiring;

        StatefulResolver mockResolver;

        BundleRevisionImpl mockRevisionImpl;

        BundleImpl mockBundle;

        mockResolver = mock(StatefulResolver.class);
        mockRevisionImpl = mock(BundleRevisionImpl.class);
        mockBundle = mock(BundleImpl.class);

        Logger logger = new Logger();
        Map configMap = new HashMap();
        List<BundleRevision> fragments = new ArrayList<BundleRevision>();
        List<BundleWire> wires = new ArrayList<BundleWire>();
        Map<String, BundleRevision> importedPkgs = new HashMap<String, BundleRevision>();
        Map<String, List<BundleRevision>> requiredPkgs = new HashMap<String, List<BundleRevision>>();

        when(mockRevisionImpl.getBundle()).thenReturn(mockBundle);
        when(mockBundle.getBundleId()).thenReturn(Long.valueOf(1));

        bundleWiring = new BundleWiringImpl(logger, configMap, mockResolver,
            mockRevisionImpl, fragments, wires, importedPkgs, requiredPkgs);

        when(mockBundle.getFramework()).thenReturn(mockFramework);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
        when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(
            testClassBytes);
        when(mockContent.getEntryAsBytes(testClassAsPath2)).thenReturn(
            testClassBytes2);
        when(mockContent.getEntryAsBytes(testClassAsPath3)).thenReturn(
            testClassBytes3);


        final TestBundleClassLoader bundleClassLoader = createBundleClassLoader(
            TestBundleClassLoader.class, bundleWiring);
        assertNotNull(bundleClassLoader);

        Field m_classLoader = bundleWiring.getClass().getDeclaredField("m_classLoader");
        m_classLoader.setAccessible(true);
        m_classLoader.set(bundleWiring, bundleClassLoader);

        assertTrue(bundleClassLoader.isParallel());

        final AtomicInteger loaded = new AtomicInteger();
        new Thread() {
            public void run() {
                try
                {
                    loaded.set(bundleClassLoader.findClass(testClassName2) != null ? 1 : 2);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    loaded.set(3);
                }
            }
        }.start();

        while (bundleClassLoader.m_gate.getQueueLength() == 0)
        {
            Thread.sleep(1);
        }

        final AtomicInteger loaded2 = new AtomicInteger();
        new Thread() {
            public void run() {
                try
                {
                    loaded2.set(bundleClassLoader.findClass(testClassName3) != null ? 1 : 2);
                }
                catch (ClassNotFoundException e)
                {
                    e.printStackTrace();
                    loaded2.set(3);
                }
            }
        }.start();

        while (loaded2.get() == 0)
        {
            Thread.sleep(1);
        }

        assertEquals(0, loaded.get());
        assertEquals(1, bundleClassLoader.m_gate.getQueueLength());

        loaded2.set(0);
        Thread tester = new Thread() {
            public void run() {
                try
                {
                    loaded2.set(bundleClassLoader.findClass(testClassName2) != null ? 1 : 2);
                }
                catch (ClassNotFoundException e)
                {
                    e.printStackTrace();
                    loaded2.set(3);
                }
            }
        };
        tester.start();

        Thread.sleep(100);

        assertEquals(0, loaded2.get());
        assertEquals(1, bundleClassLoader.m_gate.getQueueLength());

        bundleClassLoader.m_gate.release();


        while (loaded.get() == 0)
        {
            Thread.sleep(1);
        }

        assertEquals(1, loaded.get());

        while (loaded2.get() == 0)
        {
            Thread.sleep(1);
        }
        assertEquals(1, loaded2.get());
    }

    @Test
    public void testClassloadStress() throws Exception
    {
        ExecutorService executors = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 4);
        final List<Throwable> exceptionsNP = Collections.synchronizedList(new ArrayList<Throwable>());
        final List<Throwable> exceptionsP = Collections.synchronizedList(new ArrayList<Throwable>());

        for (int i = 0; i < 100; i++) {
            executors.submit(i % 2 == 0 ? new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        testNotParallelClassload();
                    }
                    catch (Throwable e)
                    {
                        exceptionsNP.add(e);
                    }
                }
            } : new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        testParallelClassload();
                    }
                    catch (Throwable e)
                    {
                        exceptionsP.add(e);
                    }
                }
            });
        }
        executors.shutdown();
        executors.awaitTermination(10, TimeUnit.MINUTES);
        assertTrue(exceptionsNP.toString(), exceptionsNP.isEmpty());
        assertTrue(exceptionsP.toString(), exceptionsP.isEmpty());
    }

    @Test
    public void testNotParallelClassload() throws Exception
    {

        Felix mockFramework = mock(Felix.class);
        HookRegistry hReg = mock(HookRegistry.class);
        Mockito.when(mockFramework.getHookRegistry()).thenReturn(hReg);
        Content mockContent = mock(Content.class);
        final Class testClass = TestClassSuper.class;
        final String testClassName = testClass.getName();
        final String testClassAsPath = testClassName.replace('.', '/') + ".class";
        byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);

        final Class testClass2 = TestClassChild.class;
        final String testClassName2 = testClass2.getName();
        final String testClassAsPath2 = testClassName2.replace('.', '/') + ".class";
        byte[] testClassBytes2 = createTestClassBytes(testClass2, testClassAsPath2);

        final Class testClass3 = TestClass.class;
        final String testClassName3 = testClass3.getName();
        final String testClassAsPath3 = testClassName3.replace('.', '/') + ".class";
        byte[] testClassBytes3 = createTestClassBytes(testClass3, testClassAsPath3);

        List<Content> contentPath = new ArrayList<Content>();
        contentPath.add(mockContent);
        BundleWiringImpl bundleWiring;

        StatefulResolver mockResolver;

        BundleRevisionImpl mockRevisionImpl;

        BundleImpl mockBundle;

        mockResolver = mock(StatefulResolver.class);
        mockRevisionImpl = mock(BundleRevisionImpl.class);
        mockBundle = mock(BundleImpl.class);

        Logger logger = new Logger();
        Map configMap = new HashMap();
        List<BundleRevision> fragments = new ArrayList<BundleRevision>();
        List<BundleWire> wires = new ArrayList<BundleWire>();
        Map<String, BundleRevision> importedPkgs = new HashMap<String, BundleRevision>();
        Map<String, List<BundleRevision>> requiredPkgs = new HashMap<String, List<BundleRevision>>();

        when(mockRevisionImpl.getBundle()).thenReturn(mockBundle);
        when(mockBundle.getBundleId()).thenReturn(Long.valueOf(1));

        bundleWiring = new BundleWiringImpl(logger, configMap, mockResolver,
            mockRevisionImpl, fragments, wires, importedPkgs, requiredPkgs);

        when(mockBundle.getFramework()).thenReturn(mockFramework);
        when(mockFramework.getBootPackages()).thenReturn(new String[0]);

        when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
        when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(
            testClassBytes);
        when(mockContent.getEntryAsBytes(testClassAsPath2)).thenReturn(
            testClassBytes2);
        when(mockContent.getEntryAsBytes(testClassAsPath3)).thenReturn(
            testClassBytes3);


        final TestBundleClassLoader2 bundleClassLoader = createBundleClassLoader(
            TestBundleClassLoader2.class, bundleWiring);
        assertNotNull(bundleClassLoader);

        Field m_classLoader = bundleWiring.getClass().getDeclaredField("m_classLoader");
        m_classLoader.setAccessible(true);
        m_classLoader.set(bundleWiring, bundleClassLoader);

        assertFalse(bundleClassLoader.isParallel());

        final AtomicInteger loaded = new AtomicInteger();
        new Thread() {
            public void run() {
                try
                {
                    loaded.set(bundleClassLoader.findClass(testClassName2) != null ? 1 : 2);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    loaded.set(3);
                }
            }
        }.start();

        while (bundleClassLoader.m_gate.getQueueLength() == 0)
        {
            Thread.sleep(1);
        }

        final AtomicInteger loaded2 = new AtomicInteger();
        new Thread() {
            public void run() {
                try
                {
                    loaded2.set(bundleClassLoader.findClass(testClassName3) != null ? 1 : 2);
                }
                catch (ClassNotFoundException e)
                {
                    e.printStackTrace();
                    loaded2.set(3);
                }
            }
        }.start();

        Thread.sleep(100);

        assertEquals(0, loaded.get());
        assertEquals(0, loaded2.get());
        assertEquals(1, bundleClassLoader.m_gate.getQueueLength());

        final AtomicInteger loaded3 = new AtomicInteger();
        Thread tester = new Thread() {
            public void run() {
                try
                {
                    loaded3.set(bundleClassLoader.findClass(testClassName2) != null ? 1 : 2);
                }
                catch (ClassNotFoundException e)
                {
                    e.printStackTrace();
                    loaded3.set(3);
                }
            }
        };
        tester.start();

        Thread.sleep(100);

        assertEquals(0, loaded3.get());
        assertEquals(0, loaded2.get());

        assertEquals(0, loaded.get());
        assertEquals(1, bundleClassLoader.m_gate.getQueueLength());

        bundleClassLoader.m_gate.release();


        while (loaded.get() == 0)
        {
            Thread.sleep(1);
        }

        assertEquals(1, loaded.get());

        while (loaded2.get() == 0)
        {
            Thread.sleep(1);
        }
        assertEquals(1, loaded2.get());

        while (loaded3.get() == 0)
        {
            Thread.sleep(1);
        }
        assertEquals(1, loaded3.get());
    }

    private static class TestBundleClassLoader extends BundleClassLoader
    {
        static {
            ClassLoader.registerAsParallelCapable();
        }

        Semaphore m_gate = new Semaphore(0);
        public TestBundleClassLoader(BundleWiringImpl wiring, ClassLoader parent, Logger logger)
        {
            super(wiring, parent, logger);
        }

        @Override
        protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException
        {
            if (name.startsWith("java"))
            {
                return getClass().getClassLoader().loadClass(name);
            }
            return super.loadClass(name, resolve);
        }

        @Override
        protected Class findClass(String name) throws ClassNotFoundException
        {
            if (name.startsWith("java"))
            {
                return getClass().getClassLoader().loadClass(name);
            }
            if (name.equals(TestClassSuper.class.getName()))
            {
                m_gate.acquireUninterruptibly();
            }
            return super.findClass(name);
        }
    }

    private static class TestBundleClassLoader2 extends BundleClassLoader
    {
        Semaphore m_gate = new Semaphore(0);
        public TestBundleClassLoader2(BundleWiringImpl wiring, ClassLoader parent, Logger logger)
        {
            super(wiring, parent, logger);
        }

        @Override
        protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException
        {
            if (name.startsWith("java"))
            {
                return getClass().getClassLoader().loadClass(name);
            }
            return super.loadClass(name, resolve);
        }

        @Override
        protected Class findClass(String name) throws ClassNotFoundException
        {
            if (name.startsWith("java"))
            {
                return getClass().getClassLoader().loadClass(name);
            }
            if (name.equals(TestClassSuper.class.getName()))
            {
                m_gate.acquireUninterruptibly();
            }
            return super.findClass(name);
        }

        @Override
        protected boolean isParallel()
        {
            return false;
        }
    }

    @SuppressWarnings("rawtypes")
    private byte[] createTestClassBytes(Class testClass, String testClassAsPath)
            throws IOException
    {
        InputStream testClassResourceStream = testClass.getClassLoader()
                .getResourceAsStream(testClassAsPath);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int curByte;
        while ((curByte = testClassResourceStream.read()) != -1)
        {
            baos.write(curByte);
        }
        byte[] testClassBytes = baos.toByteArray();
        return testClassBytes;
    }

    @SuppressWarnings("rawtypes")
    private <T> T createBundleClassLoader(
            Class<T> bundleClassLoaderClass, BundleWiringImpl bundleWiring)
                    throws Exception
    {
        Logger logger = new Logger();
        Constructor ctor = BundleRevisionImpl.getSecureAction().getConstructor(
                bundleClassLoaderClass,
                new Class[] { BundleWiringImpl.class, ClassLoader.class,
                        Logger.class });
        BundleRevisionImpl.getSecureAction().setAccesssible(ctor);
        T bundleClassLoader = (T) BundleRevisionImpl
                .getSecureAction().invoke(
                        ctor,
                        new Object[] { bundleWiring,
                                this.getClass().getClassLoader(), logger });
        return bundleClassLoader;
    }

    class TestClass
    {
        // An empty test class to weave.
    }

    class TestClassSuper
    {
        // An empty test class to weave.
    }

    class TestClassChild extends TestClassSuper
    {

    }

    class GoodDummyWovenHook implements WeavingHook
    {
        // Adds the awesomePublicField to a class
        @Override
        @SuppressWarnings("unchecked")
        public void weave(WovenClass wovenClass)
        {
            byte[] wovenClassBytes = wovenClass.getBytes();
            ClassNode classNode = new ClassNode();
            ClassReader reader = new ClassReader(wovenClassBytes);
            reader.accept(classNode, 0);
            classNode.fields.add(new FieldNode(Opcodes.ACC_PUBLIC,
                    "awesomePublicField", "Ljava/lang/String;", null, null));
            ClassWriter writer = new ClassWriter(reader, Opcodes.ASM4);
            classNode.accept(writer);
            wovenClass.setBytes(writer.toByteArray());
        }
    }

    class BadDefineWovenHook implements WeavingHook
    {
        // Adds the awesomePublicField twice to the class. This is bad java.
        @Override
        @SuppressWarnings("unchecked")
        public void weave(WovenClass wovenClass)
        {
            byte[] wovenClassBytes = wovenClass.getBytes();
            ClassNode classNode = new ClassNode();
            ClassReader reader = new ClassReader(wovenClassBytes);
            reader.accept(classNode, 0);
            classNode.fields.add(new FieldNode(Opcodes.ACC_PUBLIC,
                    "awesomePublicField", "Ljava/lang/String;", null, null));
            classNode.fields.add(new FieldNode(Opcodes.ACC_PUBLIC,
                    "awesomePublicField", "Ljava/lang/String;", null, null));
            ClassWriter writer = new ClassWriter(reader, Opcodes.ASM4);
            classNode.accept(writer);
            wovenClass.setBytes(writer.toByteArray());
        }
    }

    class BadDummyWovenHook implements WeavingHook
    {
        // Just Blow up
        @Override
        public void weave(WovenClass wovenClass)
        {
            throw new WeavingException("Bad Weaver!");
        }
    }

    class DummyWovenClassListener implements WovenClassListener
    {
        public List<Integer> stateList = new ArrayList<Integer>();

        @Override
        public void modified(WovenClass wovenClass)
        {
            stateList.add(wovenClass.getState());
        }
    }
}
