content: /*
   * 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.proxy.itests;
  
  import static org.junit.Assert.assertSame;
  import static org.junit.Assert.fail;
  
  import java.util.AbstractList;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.concurrent.Callable;
  
  import org.apache.aries.proxy.FinalModifierException;
  import org.apache.aries.proxy.weaving.WovenProxy;
  import org.apache.aries.proxy.weavinghook.ProxyWeavingController;
  import org.apache.aries.proxy.weavinghook.WeavingHelper;
  import org.junit.Test;
  import org.ops4j.pax.exam.Configuration;
  import org.ops4j.pax.exam.Option;
  import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
  import org.ops4j.pax.exam.spi.reactors.PerMethod;
  import org.osgi.framework.Bundle;
  import org.osgi.framework.hooks.weaving.WovenClass;
  
  @ExamReactorStrategy(PerMethod.class)
  public class WeavingProxyTest extends AbstractProxyTest
  {
  
      @Configuration
      public Option[] configuration() {
        return new Option[] //
        {
         proxyOptions()
        };
      }
      
    /**
     * This test does two things. First of all it checks that we can proxy a final 
     * class. It also validates that the class implements WovenProxy, and that the
     * delegation still works
     */
    @Test
    public void checkProxyFinalClass() throws Exception
    {
      Bundle b = bundleContext.getBundle();
      TestCallable dispatcher = new TestCallable();
      TestCallable template = new TestCallable();
      Collection<Class<?>> classes = new ArrayList<Class<?>>();
      classes.add(TestCallable.class);
      @SuppressWarnings("unchecked")
  	Callable<Object> o = (Callable<Object>) mgr.createDelegatingProxy(b, classes, 
          dispatcher, template);
      if(!(o instanceof WovenProxy))
        fail("Proxy should be woven!");
  
      Object inner = new Integer(3);
      dispatcher.setReturn(new TestCallable());
      ((TestCallable)dispatcher.call()).setReturn(inner);
  
      assertSame("Should return the same object", inner, o.call());
    }
  
    /**
     * This method checks that we correctly proxy a class with final methods.
     */
    @Test
    public void checkProxyFinalMethods() throws Exception
    {
      Bundle b = bundleContext.getBundle();
      Callable<Object> c = new TestCallable();
      Collection<Class<?>> classes = new ArrayList<Class<?>>();
      Runnable r = new Runnable() {
        public final void run() {
        }
      };
      classes.add(r.getClass());
      Object o = mgr.createDelegatingProxy(b, classes, c, r);
      if(!(o instanceof WovenProxy))
        fail("Proxy should be woven!");
    }
  
    @Test(expected = FinalModifierException.class)
    public void checkProxyController() throws Exception
    {
  
      bundleContext.registerService(ProxyWeavingController.class.getName(), new ProxyWeavingController() {
  
        public boolean shouldWeave(WovenClass arg0, WeavingHelper arg1)
        {
          return false;
        }
      }, null);
  
      Bundle b = bundleContext.getBundle();
      Callable<Object> c = new TestCallable();
      Collection<Class<?>> classes = new ArrayList<Class<?>>();
      // Don't use anonymous inner class in this test as IBM and Sun load it at a different time
      // For IBM JDK, the anonymous inner class will be loaded prior to the controller is registered.
      Callable<?> callable = new TestFinalDelegate();
      classes.add(callable.getClass());
      Object o = mgr.createDelegatingProxy(b, classes, c, callable);
      if(o instanceof WovenProxy)
        fail("Proxy should not have been woven!");
    }
  
    private static class TestFinalDelegate extends AbstractList<String> implements Callable<String> {
  
      @Override
      public String get(int location)
      {
        return null;
      }
  
      @Override
      public int size()
      {
        return 0;
      }
  
      public final String call() throws Exception
      {
        return null;
      }
    }
  }
  