//
//  ========================================================================
//  Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.osgi.test;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpContentResponse;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpService;

/**
 * Helper methods for pax-exam tests
 */
public class AbstractTestOSGi
{

	private Map<String,Bundle> _bundles;
	
	/**
	 * Note: this will run many more tests.
	 * TODO: find a better way to control this and use non-deprecated methods.
	 * @param options
	 */
	protected static void addMoreOSGiContainers(List<Option> options)
	{
        options.add(CoreOptions.equinox().version("3.6.1"));
        // equinox-3.7.1 is somehow always downloaded from the internet
        //by pax-exam. this makes the execution of the test too slow...
       // options.add(CoreOptions.equinox().version("3.7.1")); //commented to keep the tests speedy
        options.add(CoreOptions.felix().version("3.2.2"));
        options.add(CoreOptions.felix().version("4.0.2"));
	}
	
	protected Bundle getBundle(BundleContext bundleContext, String symbolicName)
	{
		if (_bundles == null)
		{
			_bundles = new HashMap<String,Bundle>();
			for (Bundle b : bundleContext.getBundles())
			{
				Bundle prevBundle = _bundles.put(b.getSymbolicName(), b);
				String err = prevBundle != null ? "2 versions of the bundle " + b.getSymbolicName() +
						" " + b.getHeaders().get("Bundle-Version") +
						" and " + prevBundle.getHeaders().get("Bundle-Version")
						: "";
				Assert.assertNull(err, prevBundle);
			}
		}
		return _bundles.get(symbolicName);
	}
	
	protected void assertActiveBundle(BundleContext bundleContext, String symbolicName) throws Exception
	{
		Bundle b = getBundle(bundleContext, symbolicName);
		Assert.assertNotNull(b);
		Assert.assertEquals(b.getSymbolicName()+" must be active.", Bundle.ACTIVE, b.getState());
	}
	
	protected void assertActiveOrResolvedBundle(BundleContext bundleContext, String symbolicName) throws Exception
	{
		Bundle b = getBundle(bundleContext, symbolicName);
		Assert.assertNotNull(b);
		if (b.getHeaders().get("Fragment-Host") == null) diagnoseNonActiveOrNonResolvedBundle(b);
		Assert.assertTrue(b.getSymbolicName()+" must be active or resolved. It was "+b.getState(), 
				b.getState() == Bundle.ACTIVE || b.getState() == Bundle.RESOLVED);
	}
	
	protected void assertAllBundlesActiveOrResolved(BundleContext bundleContext)
	{
		for (Bundle b : bundleContext.getBundles())
		{
			if (b.getState() == Bundle.INSTALLED)
			{
				diagnoseNonActiveOrNonResolvedBundle(b);
			}
			Assert.assertTrue(b.getState() == Bundle.ACTIVE || b.getState() == Bundle.RESOLVED);
		}
	}

	protected boolean diagnoseNonActiveOrNonResolvedBundle(Bundle b)
	{
		if (b.getState() != Bundle.ACTIVE && b.getHeaders().get("Fragment-Host") == null)
		{
			try
			{
				System.err.println("Trying to start the bundle "+b.getSymbolicName()+
						" that was supposed to be active or resolved.");
				b.start();
				System.err.println(b.getSymbolicName() + " did start");
				return true;
			}
			catch (Throwable t)
			{
				System.err.println(b.getSymbolicName() + " failed to start");
				t.printStackTrace(System.err);
				return false;
			}
		}
		System.err.println(b.getSymbolicName() + " was already started");
		return false;
	}
	
	protected void debugBundles(BundleContext bundleContext)
	{
        Map<String,Bundle> bundlesIndexedBySymbolicName = new HashMap<String, Bundle>();
        System.err.println("Active " + Bundle.ACTIVE);
        System.err.println("RESOLVED " + Bundle.RESOLVED);
        System.err.println("INSTALLED " + Bundle.INSTALLED);
        for( Bundle b : bundleContext.getBundles() )
        {
            bundlesIndexedBySymbolicName.put(b.getSymbolicName(), b);
            System.err.println("    " + b.getSymbolicName() + " " + b.getState());
        }
	}
	
	protected SslContextFactory getSslContextFactory()
	{
		return new SslContextFactory(true);
	}
		
	protected void testHttpServiceGreetings(BundleContext bundleContext, String protocol, int port) throws Exception
	{
        assertActiveBundle(bundleContext, "org.eclipse.jetty.osgi.boot");
        
        assertActiveBundle(bundleContext, "org.eclipse.jetty.osgi.httpservice");
        assertActiveBundle(bundleContext, "org.eclipse.equinox.http.servlet");
        
        //in the OSGi world this would be bad code and we should use a bundle tracker.
        //here we purposely want to make sure that the httpService is actually ready.
        ServiceReference sr = bundleContext.getServiceReference(HttpService.class.getName());
        Assert.assertNotNull("The httpServiceOSGiBundle is started and should " +
        		"have deployed a service reference for HttpService" ,sr);
        HttpService http = (HttpService)bundleContext.getService(sr);
        http.registerServlet("/greetings", new HttpServlet() {
            private static final long serialVersionUID = 1L;
            @Override
            protected void doGet(HttpServletRequest req,
                    HttpServletResponse resp) throws ServletException,
                    IOException {
                resp.getWriter().write("Hello");
            }
        }, null, null);
        
        //now test the servlet
        HttpClient client = protocol.equals("https") ? new HttpClient(getSslContextFactory()) : new HttpClient();
        try
        {
            client.start();
            Response response = client.GET(protocol+"://127.0.0.1:"+port+"/greetings").get(5, TimeUnit.SECONDS);;
            Assert.assertEquals(HttpStatus.OK_200, response.status());
     
            String content = new String(((HttpContentResponse)response).content());
            Assert.assertEquals("Hello", content);
        }
        finally
        {
            client.stop();
        }
	}
}

@@ -2040,154 +2040,8 @@
     
- // equinox-3.7.1 is somehow always downloaded from the internet%0A        //by pax-exam. this makes the execution of the test too slow...%0A       //
  opt
@@ -2088,50 +2088,13 @@
 3.7.
-1
+0
 %22));
- //commented to keep the tests speedy
 %0A   

Add equinox-3.7.0 to the osgi frameworks tested