Project: bamboo-sonar-integration
/*
 * Licensed to Marvelution under one or more contributor license 
 * agreements.  See the NOTICE file distributed with this work 
 * for additional information regarding copyright ownership. 
 * Marvelution 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 com.marvelution.bamboo.plugins.sonar.web.proxy; 
 
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 
import java.lang.reflect.Proxy; 
 
import org.osgi.framework.Bundle; 
import org.osgi.framework.ServiceReference; 
import org.osgi.util.tracker.ServiceTracker; 
import org.springframework.util.ReflectionUtils; 
 
import com.atlassian.plugin.osgi.container.OsgiContainerException; 
 
/**
 * Helper class to get a Service using a {@link ServiceTracker} 
 * This will create a {@link Proxy} between the ClassLoaders used 
 *  
 * @author <a href="mailto:[email protected]">Mark Rekveld</a> 
 * 
 * @since 1.5.4 
 */
 
public class OsgiServiceProxy implements InvocationHandler { 
 
 private final Bundle bundle; 
 private final Object service; 
 private final Class<?> serviceClass; 
 
 /**
  * Constructor 
  * 
  * @param tracker the {@link ServiceTracker} to proxy 
  */
 
 private OsgiServiceProxy(ServiceTracker tracker) { 
  this.bundle = tracker.getServiceReference().getBundle(); 
  service = tracker.getService(); 
  serviceClass = service.getClass(); 
 
 
 /**
  * {@inheritDoc} 
  */
 
 @Override 
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
  Class<?>[] argtypes;  
  if (args != null && args.length > 0) { 
   argtypes = new Class<?>[args.length]; 
   for (int index = 0; index < args.length; index++) { 
    argtypes[index] = bundle.loadClass(args[index].getClass().getName()); 
   
  else { 
   argtypes = new Class[0]; 
  
  Method actual = ReflectionUtils.findMethod(serviceClass, method.getName(), argtypes); 
  if (actual != null) { 
   return actual.invoke(service, args); 
  else { 
   throw new InvocationTargetException(new Exception(), "Service '" + serviceClass + "' has no method with name: " + method.getName()); 
  
 
 
 /**
  * Static helper method to get a {@link OsgiServiceProxy} {@link Proxy} 
  *  
  * @param tracker the {@link ServiceTracker} to get a {@link Proxy} for 
  * @param type the {@link Class} type of the Service Object 
  * @return the {@link Proxy} 
  */
 
 @SuppressWarnings("unchecked"
 public static <T> T getServiceProxy(ServiceTracker tracker, Class<T> type) { 
  ServiceReference reference = tracker.getServiceReference(); 
  if (reference.isAssignableTo(reference.getBundle(), type.getName())) { 
   InvocationHandler handler = new OsgiServiceProxy(tracker); 
   return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, handler); 
  else { 
   throw new OsgiContainerException("Service '" + reference.getBundle().getClass() + "' is not of type " + type); 
  
 
 
}