/*
 * 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.aries.blueprint.proxy;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

import org.apache.aries.blueprint.proxy.AbstractProxyTest.TestListener;
import org.apache.aries.mocks.BundleMock;
import org.apache.aries.proxy.impl.interfaces.InterfaceProxyGenerator;
import org.apache.aries.unittest.mocks.MethodCall;
import org.apache.aries.unittest.mocks.Skeleton;
import org.apache.aries.util.ClassLoaderProxy;
import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWiring;


public class InterfaceProxyingTest {

  public final static class TestCallable implements Callable<Object> {
    
    private Object list = new Callable<Object>() {


      public Object call() throws Exception {
        return null;
      }
    };
    
    public Object call() throws Exception {
      return list;
    }
    
    public void setReturn(Object o) {
      list = o;
    }
  }

  private Bundle testBundle;

  /**
   * Extended BundleMock which handles update() and adapt() methods
   */
  public static class BundleMockEx extends BundleMock {
    private BundleWiring currentWiring = Skeleton.newMock(BundleWiring.class);

    public BundleMockEx(String name, Dictionary<?, ?> properties) {
      super(name, properties);
    }

    public <A> A adapt(Class<A> type) {
      if (type == BundleWiring.class) {
        return (A) currentWiring;
      }
      return null;
    }

    public void update() throws BundleException {
      this.currentWiring = Skeleton.newMock(BundleWiring.class);
    }
  }

  @Before
  public void setup() {
    testBundle = Skeleton.newMock(new BundleMockEx("test",
        new Hashtable<Object, Object>()), Bundle.class);
  }
  
  @Test
  public void testGetProxyInstance1() throws Exception{
    
    Collection<Class<?>> classes = new ArrayList<Class<?>>(Arrays.asList(Closeable.class));
    
    Object o = InterfaceProxyGenerator.getProxyInstance(testBundle, null, classes, constantly(null), null);
    
    assertTrue(o instanceof Closeable);
  }
  
  @Test
  public void testGetProxyInstance2() throws Exception{
    
    Collection<Class<?>> classes = new ArrayList<Class<?>>(Arrays.asList(Closeable.class,
        Iterable.class, Map.class));
    
    Object o = InterfaceProxyGenerator.getProxyInstance(testBundle, null, classes, constantly(null), null);
    
    assertTrue(o instanceof Closeable);
    assertTrue(o instanceof Iterable);
    assertTrue(o instanceof Map);
    
  }

  /**
   * Test a class whose super couldn't be woven
   */
  @Test
  public void testDelegationAndInterception() throws Exception
  {
    Collection<Class<?>> classes = new ArrayList<Class<?>>(Arrays.asList(Callable.class));
    TestListener tl = new TestListener();
    TestCallable tc = new TestCallable();
    
    Callable o = (Callable) InterfaceProxyGenerator.getProxyInstance(testBundle, 
        null, classes, tc, tl);
    
    assertCalled(tl, false, false, false);
    
    assertNull(null, o.call());
    
    assertCalled(tl, true, true, false);
    
    assertEquals(Callable.class.getMethod("call"), 
        tl.getLastMethod());

    tl.clear();
    assertCalled(tl, false, false, false);
    
    tc.setReturn(new Callable<Object>() {

 
      public Object call() throws Exception {
        throw new RuntimeException();
      }
    });
    try {
      o.call();
      fail("Should throw an exception");
    } catch (RuntimeException re) {
      assertCalled(tl, true, false, true);
      assertSame(re, tl.getLastThrowable());
    }
    
    tl.clear();
    assertCalled(tl, false, false, false);
    
    tc.setReturn(new Callable<Object>() {

     
      public Object call() throws Exception {
        try {
          throw new RuntimeException();
        } catch (RuntimeException re) {
          return new Object();
        }
      }
    });
    
    
    try {
      assertNotNull(o.call());
    } finally {
      assertCalled(tl, true, true, false);
    }
  }
  
  @Test
  public void testCaching() throws Exception {
    Collection<Class<?>> classes = new ArrayList<Class<?>>(Arrays.asList(Closeable.class));
    
    Object o1 = InterfaceProxyGenerator.getProxyInstance(testBundle, null, classes, constantly(null), null);
    Object o2 = InterfaceProxyGenerator.getProxyInstance(testBundle, null, classes, constantly(null), null);
    
    assertSame(o1.getClass(), o2.getClass());
  }
  
  @Test
  public void testComplexInterface() throws Exception {
    Collection<Class<?>> classes = new ArrayList<Class<?>>(Arrays.asList(ProxyTestInterface.class));
    
    final TestCallable tc = new TestCallable();
    tc.setReturn(5);
    
    Object o = InterfaceProxyGenerator.getProxyInstance(testBundle, null, classes, constantly(tc), null);
    
    assertTrue(o instanceof ProxyTestInterface);
    
    assertTrue(o instanceof Callable);
    
    assertEquals(5, ((Callable)o).call());
  }
  
  @Test
  public void testHandlesObjectMethods() throws Exception {
      TestListener listener = new TestListener();
      List<String> list = Arrays.asList("one", "two", "three");
      Object proxied = InterfaceProxyGenerator.getProxyInstance(testBundle, null, Arrays.<Class<?>>asList(List.class), constantly(list), listener);
      
      // obeys hashCode and equals, they *are* on the interface (actually they're
      // on several interfaces, we process them in alphabetical order, so Collection
      // comes ahead of List.
      assertTrue(proxied.equals(Arrays.asList("one", "two", "three")));
      assertEquals(Collection.class.getMethod("equals", Object.class), listener.getLastMethod());
      listener.clear();
      assertEquals(Arrays.asList("one", "two", "three").hashCode(), proxied.hashCode());
      assertEquals(Collection.class.getMethod("hashCode"), listener.getLastMethod());
      listener.clear();
      // and toString
      assertEquals(list.toString(), proxied.toString());
      assertEquals(Object.class.getMethod("toString"), listener.getLastMethod());
      listener.clear();
      
      Runnable runnable = new Runnable() {
        public void run() {}
      };
      proxied = InterfaceProxyGenerator.getProxyInstance(testBundle, null, Arrays.<Class<?>>asList(Runnable.class), constantly(runnable), listener);
      
      // obeys hashCode and equals, they *are not* on the interface
      assertTrue(proxied.equals(runnable));
      assertEquals(Object.class.getMethod("equals", Object.class), listener.getLastMethod());
      listener.clear();
      assertEquals(runnable.hashCode(), proxied.hashCode());
      assertEquals(Object.class.getMethod("hashCode"), listener.getLastMethod());
      listener.clear();
  }
  
  private static class TestClassLoader extends ClassLoader {
      public TestClassLoader() throws Exception {
          
          InputStream is = TestClassLoader.class.getClassLoader().getResourceAsStream("org/apache/aries/blueprint/proxy/TestInterface.class");
          ByteArrayOutputStream bout = new ByteArrayOutputStream();

          int b;
          while ((b = is.read()) != -1) {
              bout.write(b);
          }
          
          is.close();
          
          byte[] bytes = bout.toByteArray();
          defineClass("org.apache.aries.blueprint.proxy.TestInterface", bytes, 0, bytes.length);
      }
  }
  
  @Test
  public void testNoStaleProxiesForRefreshedBundle() throws Exception {
      Bundle bundle = (Bundle) Skeleton.newMock(new Class<?>[] { Bundle.class, ClassLoaderProxy.class });      
      Skeleton skel = Skeleton.getSkeleton(bundle);
      
      TestClassLoader loader = new TestClassLoader();
      skel.setReturnValue(new MethodCall(ClassLoaderProxy.class, "getClassLoader"), loader);
      skel.setReturnValue(new MethodCall(Bundle.class, "getLastModified"), 10l);
      skel.setReturnValue(new MethodCall(Bundle.class, "adapt", BundleWiring.class), Skeleton.newMock(BundleWiring.class));

      Class<?> clazz = loader.loadClass("org.apache.aries.blueprint.proxy.TestInterface");
      
      Object proxy = InterfaceProxyGenerator.getProxyInstance(bundle, null, Arrays.<Class<?>>asList(clazz), constantly(null), null);
      assertTrue(clazz.isInstance(proxy));

      ClassLoader parent1 = proxy.getClass().getClassLoader().getParent();
      
      /* Now again but with a changed classloader as if the bundle had refreshed */
      
      TestClassLoader loaderToo = new TestClassLoader();
      skel.setReturnValue(new MethodCall(ClassLoaderProxy.class, "getClassLoader"), loaderToo);
      skel.setReturnValue(new MethodCall(Bundle.class, "getLastModified"), 20l);

      // let's change the returned revision
      skel.setReturnValue(new MethodCall(Bundle.class, "adapt", BundleWiring.class), Skeleton.newMock(BundleWiring.class));
      
      Class<?> clazzToo = loaderToo.loadClass("org.apache.aries.blueprint.proxy.TestInterface");
      
      Object proxyToo = InterfaceProxyGenerator.getProxyInstance(bundle, null, Arrays.<Class<?>>asList(clazzToo), constantly(null), null);
      assertTrue(clazzToo.isInstance(proxyToo));

      ClassLoader parent2= proxyToo.getClass().getClassLoader().getParent();

      // parents should be different, as the are the classloaders of different bundle revisions
      assertTrue(parent1 != parent2);
  }

  protected void assertCalled(TestListener listener, boolean pre, boolean post, boolean ex) {
    assertEquals(pre, listener.preInvoke);
    assertEquals(post, listener.postInvoke);
    assertEquals(ex, listener.postInvokeExceptionalReturn);
  }
  
  private Callable<Object> constantly(final Object result) {
      return new Callable<Object>() {
          public Object call() throws Exception {
              return result;
          }             
        };
  }
}
