/*
 * 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.scr.integration;

import static org.ops4j.pax.exam.CoreOptions.frameworkProperty;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.provision;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
import static org.ops4j.pax.tinybundles.core.TinyBundles.bundle;
import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;

import javax.inject.Inject;

import org.apache.felix.scr.impl.ComponentCommands;
import org.apache.felix.scr.integration.components.SimpleComponent;
import org.apache.felix.service.command.Converter;
import org.junit.After;
import org.junit.Before;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.OptionUtils;
import org.ops4j.pax.exam.ProbeBuilder;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.namespace.extender.ExtenderNamespace;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentFactory;
import org.osgi.service.component.ComponentInstance;
import org.osgi.service.component.runtime.ServiceComponentRuntime;
import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
import org.osgi.service.log.LogService;
import org.osgi.service.log.Logger;
import org.osgi.service.log.LoggerConsumer;
import org.osgi.service.log.LoggerFactory;
import org.osgi.util.tracker.ServiceTracker;

import junit.framework.Assert;
import junit.framework.TestCase;

public abstract class ComponentTestBase
{

    @Inject
    protected BundleContext bundleContext;

    protected Bundle bundle;

    protected ServiceTracker<ServiceComponentRuntime, ServiceComponentRuntime> scrTracker;

    protected ServiceTracker<ConfigurationAdmin, ConfigurationAdmin> configAdminTracker;

    // the name of the system property providing the bundle file to be installed and tested
    protected static final String BUNDLE_JAR_SYS_PROP = "project.bundle.file";

    // the default bundle jar file name
    protected static final String BUNDLE_JAR_DEFAULT = "target/scr.jar";

    protected static final String PROP_NAME = "theValue";
    protected static final Dictionary<String, Object> theConfig;

    // the JVM option to set to enable remote debugging
    protected static final String DEBUG_VM_OPTION = "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=30303";

    // the actual JVM option set, extensions may implement a static
    // initializer overwriting this value to have the configuration()
    // method include it when starting the OSGi framework JVM
    protected static String paxRunnerVmOption = null;

    //To investigate any problems at all set to "debug"
    protected static String DS_LOGLEVEL = "error";

    protected static String bsnVersionUniqueness = "single";

    // the descriptor file to use for the installed test bundle
    protected static String descriptorFile = "/integration_test_simple_components.xml";
    protected static String COMPONENT_PACKAGE = "org.apache.felix.scr.integration.components";

    protected static boolean NONSTANDARD_COMPONENT_FACTORY_BEHAVIOR = false;
    
    protected static boolean CACHE_META_DATA = false;
    
    protected volatile Log log;

    protected static String[] ignoredWarnings; //null unless you need it.

    //set to true to only get last 1000 lines of log.
    protected static boolean restrictedLogging;

    protected static String felixCaVersion = System.getProperty( "felix.ca.version" );

    protected static final String PROP_NAME_FACTORY = ComponentTestBase.PROP_NAME + ".factory";

    static
    {
        theConfig = new Hashtable<>();
        theConfig.put( PROP_NAME, PROP_NAME );
    }

    @ProbeBuilder
    public TestProbeBuilder extendProbe(TestProbeBuilder builder)
    {
        builder.setHeader( "Export-Package",
                "org.apache.felix.scr.integration.components,"
                        + "org.apache.felix.scr.integration.components.activatesignature,"
                        + "org.apache.felix.scr.integration.components.annoconfig,"
                        + "org.apache.felix.scr.integration.components.circular,"
                        + "org.apache.felix.scr.integration.components.circularFactory,"
                        + "org.apache.felix.scr.integration.components.concurrency,"
                        + "org.apache.felix.scr.integration.components.deadlock,"
                        + "org.apache.felix.scr.integration.components.felix3680,"
                        + "org.apache.felix.scr.integration.components.felix3680_2,"
                        + "org.apache.felix.scr.integration.components.felix4984,"
                        + "org.apache.felix.scr.integration.components.felix5248,"
                        + "org.apache.felix.scr.integration.components.felix5276,"
                        + "org.apache.felix.scr.integration.components.metadata.cache" );
        builder.setHeader( "Import-Package", "org.apache.felix.scr.component" );
        builder.setHeader( "Bundle-ManifestVersion", "2" );
        return builder;
    }

    @Configuration
    public static Option[] configuration()
    {
        final String bundleFileName = System.getProperty( BUNDLE_JAR_SYS_PROP, BUNDLE_JAR_DEFAULT );
        final File bundleFile = new File( bundleFileName );
        if ( !bundleFile.canRead() )
        {
            throw new IllegalArgumentException( "Cannot read from bundle file " + bundleFileName + " specified in the "
                    + BUNDLE_JAR_SYS_PROP + " system property" );
        }

        final Option[] base = options(
                provision(
                        CoreOptions.bundle( bundleFile.toURI().toString() ),
                        mavenBundle( "org.ops4j.pax.tinybundles", "tinybundles", "1.0.0" ),
                        mavenBundle( "org.osgi", "org.osgi.service.log", "1.4.0"),
                        mavenBundle( "org.osgi", "org.osgi.util.pushstream", "1.0.0"),
                        mavenBundle( "org.apache.felix", "org.apache.felix.configadmin", felixCaVersion ) ),
                        mavenBundle( "org.osgi", "org.osgi.util.promise"),
                        mavenBundle( "org.osgi", "org.osgi.util.function"),
                        mavenBundle( "org.ops4j.pax.url", "pax-url-aether"),
                junitBundles(), frameworkProperty( "org.osgi.framework.bsnversion" ).value( bsnVersionUniqueness ),
                systemProperty( "ds.factory.enabled" ).value( Boolean.toString( NONSTANDARD_COMPONENT_FACTORY_BEHAVIOR ) ),
                systemProperty( "ds.loglevel" ).value( DS_LOGLEVEL ),
                systemProperty( "ds.cache.metadata" ).value( Boolean.toString(CACHE_META_DATA) )

                );
        final Option vmOption = ( paxRunnerVmOption != null )? CoreOptions.vmOption( paxRunnerVmOption ): null;
        NONSTANDARD_COMPONENT_FACTORY_BEHAVIOR = false;
        return OptionUtils.combine( base, vmOption );
    }

    @Before
    public void setUp() throws BundleException
    {
        log = new Log( restrictedLogging, ignoredWarnings );
        log.start();
        bundleContext.addFrameworkListener( log );
        bundleContext.registerService(
            new String[] { LogService.class.getName(), LoggerFactory.class.getName() },
            log, null);

        scrTracker = new ServiceTracker<>( bundleContext,
                ServiceComponentRuntime.class, null );
        scrTracker.open();
        configAdminTracker = new ServiceTracker<>( bundleContext,
                ConfigurationAdmin.class, null );
        configAdminTracker.open();

        if( descriptorFile != null ) {
            bundle = installBundle( descriptorFile, COMPONENT_PACKAGE );
            bundle.start();
        }
    }

    @After
    public void tearDown() throws BundleException
    {
        try
        {
            if ( bundle != null && bundle.getState() != Bundle.UNINSTALLED )
            {
                bundle.uninstall();
                bundle = null;
            }

            configAdminTracker.close();
            configAdminTracker = null;
            scrTracker.close();
            scrTracker = null;
        }
        catch (IllegalStateException e)
        {
            // not sure why this is thrown
        }
        finally
        {
            log.stop();
        }
    }

    protected Collection<ComponentDescriptionDTO> getComponentDescriptions(Bundle... bundles)
    {
        ServiceComponentRuntime scr = scrTracker.getService();
        if ( scr == null )
        {
            TestCase.fail( "no ServiceComponentRuntime" );
        }
        return scr.getComponentDescriptionDTOs(bundles);
    }

    protected ComponentDescriptionDTO findComponentDescriptorByName(String name)
    {
        ServiceComponentRuntime scr = scrTracker.getService();
        if ( scr == null )
        {
            TestCase.fail( "no ServiceComponentRuntime" );
        }
        return scr.getComponentDescriptionDTO( bundle, name );
    }

    protected Collection<ComponentConfigurationDTO> findComponentConfigurationsByName(Bundle b, String name,
            int expected)
    {
        ServiceComponentRuntime scr = scrTracker.getService();
        if ( scr == null )
        {
            TestCase.fail( "no ServiceComponentRuntime" );
        }
        ComponentDescriptionDTO cd = scr.getComponentDescriptionDTO( b, name );
        Collection<ComponentConfigurationDTO> ccs = scr.getComponentConfigurationDTOs( cd );

        if ( expected != 0 )
        {
            String sep = "[";
            StringBuffer sb = new StringBuffer();
            for ( Map.Entry<Integer, String> entry : STATES.entrySet() )
            {
                if ( ( expected & entry.getKey() ) != 0 )
                {
                    sb.append( sep ).append( entry.getValue() );
                    sep = ", ";
                }
            }
            sb.append( "]" );
            for ( ComponentConfigurationDTO cc : ccs )
            {
                Assert.assertTrue(
                        "for ComponentConfiguration name: " + cc.description.name + " properties" + cc.properties
                        + "Expected one of state " + sb.toString() + " but was " + STATES.get( cc.state ),
                        ( expected & cc.state ) == cc.state );
            }
        }
        return ccs;
    }

    protected Collection<ComponentConfigurationDTO> findComponentConfigurationsByName(String name, int expected)
    {
        return findComponentConfigurationsByName( bundle, name, expected );
    }

    protected ComponentConfigurationDTO findComponentConfigurationByName(Bundle b, String name, int expected)
    {
        Collection<ComponentConfigurationDTO> ccs = findComponentConfigurationsByName( b, name, expected );
        Assert.assertEquals( 1, ccs.size() );
        return ccs.iterator().next();
    }

    protected ComponentConfigurationDTO findComponentConfigurationByName(String name, int expected)
    {
        return findComponentConfigurationByName( bundle, name, expected );
    }

    static final Map<Integer, String> STATES = new HashMap<>();

    static
    {
        STATES.put( ComponentConfigurationDTO.UNSATISFIED_REFERENCE,
                "Unsatisfied (" + ComponentConfigurationDTO.UNSATISFIED_REFERENCE + ")" );
        STATES.put( ComponentConfigurationDTO.SATISFIED, "Satisified (" + ComponentConfigurationDTO.SATISFIED + ")" );
        STATES.put( ComponentConfigurationDTO.ACTIVE, "Active (" + ComponentConfigurationDTO.ACTIVE + ")" );
    }

    protected ComponentConfigurationDTO getDisabledConfigurationAndEnable(Bundle b, String name, int initialState)
            throws InvocationTargetException, InterruptedException
    {
        int count = 1;
        Collection<ComponentConfigurationDTO> ccs = getConfigurationsDisabledThenEnable( b, name, count, initialState );
        ComponentConfigurationDTO cc = ccs.iterator().next();
        return cc;
    }

    protected ComponentConfigurationDTO getDisabledConfigurationAndEnable(String name, int initialState)
            throws InvocationTargetException, InterruptedException
    {
        return getDisabledConfigurationAndEnable( bundle, name, initialState );
    }

    protected Collection<ComponentConfigurationDTO> getConfigurationsDisabledThenEnable(Bundle b, String name,
            int count, int initialState) throws InvocationTargetException, InterruptedException
    {
        ServiceComponentRuntime scr = scrTracker.getService();
        if ( scr == null )
        {
            TestCase.fail( "no ServiceComponentRuntime" );
        }
        ComponentDescriptionDTO cd = scr.getComponentDescriptionDTO( b, name );
        Assert.assertFalse( "Expected component disabled", scr.isComponentEnabled( cd ) );
        scr.enableComponent( cd ).getValue();
        Assert.assertTrue( "Expected component enabled", scr.isComponentEnabled( cd ) );

        Collection<ComponentConfigurationDTO> ccs = scr.getComponentConfigurationDTOs( cd );
        Assert.assertEquals( count, ccs.size() );
        for ( ComponentConfigurationDTO cc : ccs )
        {
            Assert.assertEquals( "Expected state " + STATES.get( initialState ) + " but was " + STATES.get( cc.state ),
                    initialState, cc.state );
        }
        return ccs;
    }

    protected Collection<ComponentConfigurationDTO> getConfigurationsDisabledThenEnable(String name, int count,
            int initialState) throws InvocationTargetException, InterruptedException
    {
        return getConfigurationsDisabledThenEnable( bundle, name, count, initialState );
    }

    protected ComponentDescriptionDTO checkConfigurationCount(Bundle b, String name, int count, int expectedState)
    {
        ServiceComponentRuntime scr = scrTracker.getService();
        if ( scr == null )
        {
            TestCase.fail( "no ServiceComponentRuntime" );
        }
        ComponentDescriptionDTO cd = scr.getComponentDescriptionDTO( b, name );
        Assert.assertTrue( "Expected component enabled", scr.isComponentEnabled( cd ) );

        Collection<ComponentConfigurationDTO> ccs = scr.getComponentConfigurationDTOs( cd );
        Assert.assertEquals( count, ccs.size() );
        if ( expectedState != -1 )
        {
            for ( ComponentConfigurationDTO cc : ccs )
            {
                Assert.assertEquals(
                        "Expected state " + STATES.get( expectedState ) + " but was " + STATES.get( cc.state ),
                        expectedState, cc.state );
            }
        }
        return cd;
    }

    protected ComponentDescriptionDTO checkConfigurationCount(String name, int count, int expectedState)
    {
        return checkConfigurationCount( bundle, name, count, expectedState );
    }

    protected <S> S getServiceFromConfiguration(ComponentConfigurationDTO dto, Class<S> clazz)
    {
        long id = dto.id;
        String filter = "(component.id=" + id + ")";
        Collection<ServiceReference<S>> srs;
        try
        {
            srs = bundleContext.getServiceReferences( clazz, filter );
            Assert.assertEquals( "Nothing for filter: " + filter, 1, srs.size() );
            ServiceReference<S> sr = srs.iterator().next();
            S s = bundleContext.getService( sr );
            Assert.assertNotNull( s );
            return s;
        }
        catch ( InvalidSyntaxException e )
        {
            TestCase.fail( e.getMessage() );
            return null;//unreachable in fact
        }
    }

    protected <S> void ungetServiceFromConfiguration(ComponentConfigurationDTO dto, Class<S> clazz)
    {
        long id = dto.id;
        String filter = "(component.id=" + id + ")";
        Collection<ServiceReference<S>> srs;
        try
        {
            srs = bundleContext.getServiceReferences( clazz, filter );
            Assert.assertEquals( 1, srs.size() );
            ServiceReference<S> sr = srs.iterator().next();
            bundleContext.ungetService( sr );
        }
        catch ( InvalidSyntaxException e )
        {
            TestCase.fail( e.getMessage() );
        }
    }

    protected void enableAndCheck(ComponentDescriptionDTO cd) throws InvocationTargetException, InterruptedException
    {
        ServiceComponentRuntime scr = scrTracker.getService();
        if ( scr != null )
        {
            scr.enableComponent( cd ).getValue();
            Assert.assertTrue( "Expected component enabled", scr.isComponentEnabled( cd ) );
        }
        else
        {
            throw new NullPointerException( "no ServiceComponentRuntime" );
        }

    }

    protected void disableAndCheck(ComponentConfigurationDTO cc) throws InvocationTargetException, InterruptedException
    {
        ComponentDescriptionDTO cd = cc.description;
        disableAndCheck( cd );
    }

    protected void disableAndCheck(ComponentDescriptionDTO cd) throws InvocationTargetException, InterruptedException
    {
        ServiceComponentRuntime scr = scrTracker.getService();
        if ( scr != null )
        {
            scr.disableComponent( cd ).getValue();
            Assert.assertFalse( "Expected component disabled", scr.isComponentEnabled( cd ) );
        }
        else
        {
            throw new NullPointerException( "no ServiceComponentRuntime" );
        }
    }

    protected void disableAndCheck(String name) throws InvocationTargetException, InterruptedException
    {
        ComponentDescriptionDTO cd = findComponentDescriptorByName( name );
        disableAndCheck( cd );
    }

    protected static void delay()
    {
        delay( 300 );
    }

    protected static void delay(int millis)
    {
        try
        {
            Thread.sleep( millis );
        }
        catch ( InterruptedException ie )
        {
        }
    }

    protected ConfigurationAdmin getConfigurationAdmin()
    {
        ConfigurationAdmin ca = configAdminTracker.getService();
        if ( ca == null )
        {
            TestCase.fail( "Missing ConfigurationAdmin service" );
        }
        return ca;
    }

    protected org.osgi.service.cm.Configuration configure(String pid)
    {
        return configure( pid, null );

    }

    protected org.osgi.service.cm.Configuration configure(String pid, String bundleLocation)
    {
        return configure( pid, bundleLocation, theConfig );
    }

    protected org.osgi.service.cm.Configuration configure(String pid, String bundleLocation,
            Dictionary<String, Object> props)
    {
        ConfigurationAdmin ca = getConfigurationAdmin();
        try
        {
            org.osgi.service.cm.Configuration config = ca.getConfiguration( pid, null );
            if ( bundleLocation != null )
            {
                config.setBundleLocation( bundleLocation );
            }
            config.update( props );
            return config;
        }
        catch ( IOException ioe )
        {
            TestCase.fail( "Failed updating configuration " + pid + ": " + ioe.toString() );
        }
        return null;
    }

    protected void deleteConfig(String pid)
    {
        ConfigurationAdmin ca = getConfigurationAdmin();
        try
        {
            org.osgi.service.cm.Configuration config = ca.getConfiguration( pid );
            config.delete();
        }
        catch ( IOException ioe )
        {
            TestCase.fail( "Failed deleting configuration " + pid + ": " + ioe.toString() );
        }
    }

    protected String createFactoryConfiguration(String factoryPid, String bundleLocation)
    {
        ConfigurationAdmin ca = getConfigurationAdmin();
        try
        {
            org.osgi.service.cm.Configuration config = ca.createFactoryConfiguration( factoryPid, null );
            config.update( theConfig );
            return config.getPid();
        }
        catch ( IOException ioe )
        {
            TestCase.fail( "Failed updating factory configuration " + factoryPid + ": " + ioe.toString() );
            return null;
        }
    }

    protected void deleteFactoryConfigurations(String factoryPid)
    {
        ConfigurationAdmin ca = getConfigurationAdmin();
        try
        {
            final String filter = "(service.factoryPid=" + factoryPid + ")";
            org.osgi.service.cm.Configuration[] configs = ca.listConfigurations( filter );
            if ( configs != null )
            {
                for ( org.osgi.service.cm.Configuration configuration : configs )
                {
                    configuration.delete();
                }
            }
        }
        catch ( InvalidSyntaxException ise )
        {
            // unexpected
        }
        catch ( IOException ioe )
        {
            TestCase.fail( "Failed deleting configurations " + factoryPid + ": " + ioe.toString() );
        }
    }

    //component factory test helper methods
    protected ComponentFactory getComponentFactory(final String componentfactory) throws InvalidSyntaxException
    {
        final ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(),
                "(" + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
        TestCase.assertNotNull( refs );
        TestCase.assertEquals( 1, refs.length );
        final ComponentFactory factory = (ComponentFactory) bundleContext.getService( refs[0] );
        TestCase.assertNotNull( factory );
        return factory;
    }

    protected void checkFactory(final String componentfactory, boolean expectFactoryPresent)
            throws InvalidSyntaxException
    {
        ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(),
                "(" + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
        if ( expectFactoryPresent )
        {
            TestCase.assertNotNull( refs );
            TestCase.assertEquals( 1, refs.length );

        }
        else
        {
            TestCase.assertNull( refs );
        }
    }

    protected ComponentInstance createFactoryComponentInstance(final String componentfactory)
            throws InvalidSyntaxException
    {
        Hashtable<String, String> props = new Hashtable<>();
        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );

        return createFactoryComponentInstance( componentfactory, props );
    }

    protected ComponentInstance createFactoryComponentInstance(final String componentfactory,
            Hashtable<String, String> props) throws InvalidSyntaxException
    {
        final ComponentFactory factory = getComponentFactory( componentfactory );

        final ComponentInstance instance = factory.newInstance( props );
        TestCase.assertNotNull( instance );

        TestCase.assertNotNull( instance.getInstance() );
        TestCase.assertEquals( SimpleComponent.INSTANCE, instance.getInstance() );
        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
        return instance;
    }

    protected static Class<?> getType(Object object, String desiredName)
    {
        Class<?> ccImpl = object.getClass();
        while ( ccImpl != null && !desiredName.equals( ccImpl.getSimpleName() ) )
        {
            ccImpl = ccImpl.getSuperclass();
        }
        if ( ccImpl == null )
        {
            TestCase.fail( "ComponentContext " + object + " is not a " + desiredName );
        }

        return ccImpl;
    }

    protected static Object getFieldValue(Object object, String fieldName)
    {
        try
        {
            final Field m_componentsField = getField( object.getClass(), fieldName );
            return m_componentsField.get( object );
        }
        catch ( Throwable t )
        {
            TestCase.fail( "Cannot get " + fieldName + " from " + object + ": " + t );
            return null; // keep the compiler happy
        }
    }

    protected Object getComponentManagerFromComponentInstance(Object instance)
    {
        Object cc = getFieldValue( instance, "m_componentContext" );
        return getFieldValue( cc, "m_componentManager" );
    }

    protected static Field getField(Class<?> type, String fieldName) throws NoSuchFieldException
    {
        Class<?> clazz = type;
        while ( clazz != null )
        {
            Field[] fields = clazz.getDeclaredFields();
            for ( int i = 0; i < fields.length; i++ )
            {
                Field field = fields[i];
                if ( field.getName().equals( fieldName ) )
                {
                    field.setAccessible( true );
                    return field;
                }
            }
            clazz = clazz.getSuperclass();
        }
        throw new NoSuchFieldException( fieldName );
    }

    protected Bundle installBundle(final String descriptorFile, String componentPackage) throws BundleException
    {
        return installBundle( descriptorFile, componentPackage, "simplecomponent", "0.0.11", null );
    }

    protected Bundle installBundle(final String descriptorFile, String componentPackage, String symbolicName,
            String version, String location) throws BundleException
    {
        final InputStream bundleStream = createBundleInputStream(descriptorFile, componentPackage, symbolicName,
            version);

        try
        {
            if ( location == null )
            {
                location = "test:SimpleComponent/" + System.currentTimeMillis();
            }
            return bundleContext.installBundle( location, bundleStream );
        }
        finally
        {
            try
            {
                bundleStream.close();
            }
            catch ( IOException ioe )
            {
            }
        }
    }

    protected InputStream createBundleInputStream(final String descriptorFile,
        String componentPackage, String symbolicName, String version)
    {
        final InputStream bundleStream = bundle().add("OSGI-INF/components.xml",
                getClass().getResource( descriptorFile ) )

                .set( Constants.BUNDLE_SYMBOLICNAME, symbolicName ).set( Constants.BUNDLE_VERSION, version ).set(
                        Constants.IMPORT_PACKAGE, componentPackage ).set( "Service-Component", "OSGI-INF/components.xml" ).set(
                                Constants.REQUIRE_CAPABILITY,
                                ExtenderNamespace.EXTENDER_NAMESPACE
                                + ";filter:=\"(&(osgi.extender=osgi.component)(version>=1.3)(!(version>=2.0)))\"" ).build(
                                        withBnd() );
        return bundleStream;
    }

    //Code copied from ScrCommand to make it easier to find out what your test components are actually doing.
    //    @Test
    public void testDescription() throws Exception {
        PrintStream out = System.out;
        info( new PrintWriter( out ) );
    }

    private static class InfoWriter extends ComponentCommands
    {

        protected InfoWriter(ServiceComponentRuntime scrService)
        {
            super( null, scrService, null );
        }

    }

    void info(PrintWriter out) throws Exception {
        ServiceComponentRuntime scr = scrTracker.getService();
        if ( scr == null )
        {
            TestCase.fail( "no ServiceComponentRuntime" );
        }
        InfoWriter iw = new InfoWriter(scr);
        out.print(iw.format(iw.list(), Converter.LINE));
    }

    protected boolean isAtLeastR5()
    {
        try
        {
            Method m = org.osgi.service.cm.Configuration.class.getDeclaredMethod( "getChangeCount" );
            return true;
        }
        catch ( SecurityException e )
        {
            throw new RuntimeException( e );
        }
        catch ( NoSuchMethodException e )
        {
            return false;
        }
    }

    // Used to ignore logs displayed by the framework from stdout.
    // (the log service will log it because it listen to fwk error
    // events ...).
    static class NullStdout extends PrintStream
    {
        NullStdout()
        {
            super( new OutputStream()
            {
                @Override
                public void write(int b) throws IOException
                {
                }
            } );
        }
    }

    public static class LogEntry
    {
        private final String m_msg;
        private final int m_level;
        private final Throwable m_err;
        private final long m_time;
        private final Thread m_thread;

        LogEntry(int level, String msg, Throwable t)
        {
            m_level = level;
            m_msg = msg;
            m_err = t;
            m_time = System.currentTimeMillis();
            m_thread = Thread.currentThread();
        }

        @Override
        public String toString()
        {
            return m_msg;
        }

        public int getLevel()
        {
            return m_level;
        }

        public String getMessage()
        {
            return m_msg;
        }

        public Throwable getError()
        {
            return m_err;
        }

        public long getTime()
        {
            return m_time;
        }

        public Thread getThread()
        {
            return m_thread;
        }
    }

    public static class Log implements LogService, Logger, FrameworkListener, Runnable
    {
        private static final int RESTRICTED_LOG_SIZE = 1000;
        private final SimpleDateFormat m_sdf = new SimpleDateFormat( "HH:mm:ss,S" );
        private final static PrintStream m_out = new PrintStream(
                new BufferedOutputStream( new FileOutputStream( FileDescriptor.err ), 128 ) );
        private final List<String> m_warnings = Collections.synchronizedList( new ArrayList<String>() );
        private LinkedBlockingQueue<LogEntry> m_logQueue = new LinkedBlockingQueue<>();
        private volatile Thread m_logThread;
        private volatile PrintStream m_realOut;
        private volatile PrintStream m_realErr;
        private String[] ignoredWarnings;

        protected Throwable firstFrameworkThrowable;

        private final boolean restrictedLogging;
        private final String[] log = new String[1000];
        private int i = 0;

        public Log(boolean restrictedLogging, String[] ignoredWarnings)
        {
            this.restrictedLogging = restrictedLogging;
            this.ignoredWarnings = ignoredWarnings;
        }

        public void start()
        {
            m_realOut = System.out;
            m_realErr = System.err;
            System.setOut( new NullStdout() );
            System.setErr( new NullStdout() );
            m_logThread = new Thread( this );
            m_logThread.start();
        }

        public void stop()
        {
            System.setOut( m_realOut );
            System.setErr( m_realErr );
            if ( restrictedLogging )
            {
                for ( int j = 0; j < RESTRICTED_LOG_SIZE; j++ )
                {
                    if ( log[i] != null )
                    {
                        m_realErr.println( log[i++] );
                    }
                    if ( i == RESTRICTED_LOG_SIZE )
                        i = 0;
                }
            }
            else
            {
                m_out.flush();
            }
            m_warnings.clear();
            m_logThread.interrupt();
            try
            {
                m_logThread.join();
            }
            catch ( InterruptedException e )
            {
            }
        }

        List<String> foundWarnings()
        {
            return m_warnings;
        }

        Throwable getFirstFrameworkThrowable()
        {
            return firstFrameworkThrowable;
        }

        @Override
        public void run()
        {
            try
            {
                LogEntry entry = null;
                while ( true )
                {
                    entry = m_logQueue.take();
                    if ( entry.getLevel() <= 2 && acceptWarning( entry.getMessage() ) )
                    {
                        if ( m_warnings.size() < 1024 )
                        {
                            m_warnings.add( entry.getMessage() );
                        }
                        else
                        {
                            // Avoid out of memory ...
                            m_warnings.set( 1023, "Unexpected errors logged. Please look at previous logs" );
                        }
                    }

                    StringWriter sw = new StringWriter();
                    sw.append( "log level: " + entry.getLevel() );
                    sw.append( " D=" );
                    sw.append( m_sdf.format( new Date( entry.getTime() ) ) );
                    sw.append( " T=" + entry.getThread() );
                    sw.append( ": " );
                    sw.append( entry.getMessage() );
                    if ( entry.getError() != null )
                    {
                        sw.append( System.getProperty( "line.separator" ) );
                        PrintWriter pw = new PrintWriter( sw );
                        entry.getError().printStackTrace( pw );
                        pw.flush();
                    }
                    if ( restrictedLogging )
                    {
                        log[i++] = sw.toString();
                        if ( i == RESTRICTED_LOG_SIZE )
                            i = 0;
                    }
                    else
                    {
                        m_out.println( sw.toString() );
                        m_out.flush();
                    }
                }
            }
            catch ( InterruptedException e )
            {
                return;
            }
        }

        // ------------- FrameworkListener -----------------------------------------------------------

        private boolean acceptWarning(String message)
        {
            if ( ignoredWarnings != null )
            {
                for ( String ignore : ignoredWarnings )
                {
                    if ( message.contains( ignore ) )
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        @Override
        public void frameworkEvent(final FrameworkEvent event)
        {
            int eventType = event.getType();
            String msg = getFrameworkEventMessage( eventType );
            int level = ( eventType == FrameworkEvent.ERROR )? LogService.LOG_ERROR: LogService.LOG_WARNING;
            log( level, msg, event.getThrowable() );
            if ( event.getThrowable() != null && firstFrameworkThrowable == null )
            {
                firstFrameworkThrowable = event.getThrowable();
            }
        }

        // ------------ LogService ----------------------------------------------------------------

        @Override
        public void log(int level, String message)
        {
            log( level, message, null );
        }

        @Override
        public void log(int level, String message, Throwable exception)
        {
            if ( level > getEnabledLogLevel() )
            {
                return;
            }
            m_logQueue.offer( new LogEntry( level, message, exception ) );
        }

        @Override
        public void log(ServiceReference sr, int osgiLevel, String message)
        {
            log( sr, osgiLevel, message, null );
        }

        @Override
        public void log(ServiceReference sr, int level, String msg, Throwable exception)
        {
            if ( sr != null )
            {
                StringBuilder sb = new StringBuilder();
                Object serviceId = sr.getProperty( Constants.SERVICE_ID );
                if ( serviceId != null )
                {
                    sb.append( "[" + serviceId.toString() + "] " );
                }
                sb.append( msg );
                log( level, sb.toString(), exception );
            }
            else
            {
                log( level, msg, exception );
            }
        }

        private int getEnabledLogLevel()
        {
            if ( DS_LOGLEVEL.regionMatches( true, 0, "err", 0, "err".length() ) )
            {
                return LogService.LOG_ERROR;
            }
            else if ( DS_LOGLEVEL.regionMatches( true, 0, "warn", 0, "warn".length() ) )
            {
                return LogService.LOG_WARNING;
            }
            else if ( DS_LOGLEVEL.regionMatches( true, 0, "info", 0, "info".length() ) )
            {
                return LogService.LOG_INFO;
            }
            else
            {
                return LogService.LOG_DEBUG;
            }
        }

        private String getFrameworkEventMessage(int event)
        {
            switch (event)
            {
            case FrameworkEvent.ERROR:
                return "FrameworkEvent: ERROR";
            case FrameworkEvent.INFO:
                return "FrameworkEvent INFO";
            case FrameworkEvent.PACKAGES_REFRESHED:
                return "FrameworkEvent: PACKAGE REFRESHED";
            case FrameworkEvent.STARTED:
                return "FrameworkEvent: STARTED";
            case FrameworkEvent.STARTLEVEL_CHANGED:
                return "FrameworkEvent: STARTLEVEL CHANGED";
            case FrameworkEvent.WARNING:
                return "FrameworkEvent: WARNING";
            default:
                return null;
            }
        }

        @Override
        public <L extends Logger> L getLogger(String name, Class<L> loggerType)
        {
            return (L) this;
        }

        @Override
        public Logger getLogger(String name)
        {
            return this;
        }

        @Override
        public Logger getLogger(Class<?> clazz)
        {
            return this;
        }

        @Override
        public <L extends Logger> L getLogger(Class<?> clazz, Class<L> loggerType)
        {
            return (L) this;
        }

        @SuppressWarnings("unchecked")
        @Override
        public <L extends Logger> L getLogger(Bundle bundle, String name,
            Class<L> loggerType)
        {
            return (L) this;
        }


        @Override
        public String getName()
        {
            return null;
        }

        @Override
        public boolean isTraceEnabled()
        {
            return false;
        }

        @Override
        public void trace(String message)
        {
        }

        @Override
        public void trace(String format, Object arg)
        {
        }

        @Override
        public void trace(String format, Object arg1, Object arg2)
        {
        }

        @Override
        public void trace(String format, Object... arguments)
        {
        }

        @Override
        public <E extends Exception> void trace(LoggerConsumer<E> consumer) throws E
        {
        }

        @Override
        public boolean isDebugEnabled()
        {
            return false;
        }

        @Override
        public void debug(String message)
        {
        }

        @Override
        public void debug(String format, Object arg)
        {
        }

        @Override
        public void debug(String format, Object arg1, Object arg2)
        {
        }

        @Override
        public void debug(String format, Object... arguments)
        {
        }

        @Override
        public <E extends Exception> void debug(LoggerConsumer<E> consumer) throws E
        {
        }

        @Override
        public boolean isInfoEnabled()
        {
            return false;
        }

        @Override
        public void info(String message)
        {
        }

        @Override
        public void info(String format, Object arg)
        {
        }

        @Override
        public void info(String format, Object arg1, Object arg2)
        {
        }

        @Override
        public void info(String format, Object... arguments)
        {
        }

        @Override
        public <E extends Exception> void info(LoggerConsumer<E> consumer) throws E
        {
        }

        @Override
        public boolean isWarnEnabled()
        {
            return false;
        }

        @Override
        public void warn(String message)
        {
        }

        @Override
        public void warn(String format, Object arg)
        {
        }

        @Override
        public void warn(String format, Object arg1, Object arg2)
        {
        }

        @Override
        public void warn(String format, Object... arguments)
        {
        }

        @Override
        public <E extends Exception> void warn(LoggerConsumer<E> consumer) throws E
        {
        }

        @Override
        public boolean isErrorEnabled()
        {
            return false;
        }

        @Override
        public void error(String message)
        {
        }

        @Override
        public void error(String format, Object arg)
        {
        }

        @Override
        public void error(String format, Object arg1, Object arg2)
        {
        }

        @Override
        public void error(String format, Object... arguments)
        {
        }

        @Override
        public <E extends Exception> void error(LoggerConsumer<E> consumer) throws E
        {
        }

        @Override
        public void audit(String message)
        {
        }

        @Override
        public void audit(String format, Object arg)
        {
        }

        @Override
        public void audit(String format, Object arg1, Object arg2)
        {
        }

        @Override
        public void audit(String format, Object... arguments)
        {
        }
    }
}
