View Javadoc

1   package com.atlassian.plugin.osgi.hostcomponents.impl;
2   
3   import org.apache.commons.logging.Log;
4   import org.apache.commons.logging.LogFactory;
5   import org.osgi.framework.BundleContext;
6   import org.osgi.framework.ServiceRegistration;
7   
8   import java.util.*;
9   import java.lang.reflect.Proxy;
10  import java.lang.reflect.InvocationHandler;
11  import java.lang.reflect.Method;
12  import java.lang.reflect.InvocationTargetException;
13  
14  import com.atlassian.plugin.osgi.hostcomponents.InstanceBuilder;
15  import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
16  import com.atlassian.plugin.osgi.hostcomponents.HostComponentRegistration;
17  
18  /**
19   * Default component registrar that also can write registered host components into the OSGi service registry
20   */
21  public class DefaultComponentRegistrar implements ComponentRegistrar
22  {
23      private List<HostComponentRegistration> registry = new ArrayList<HostComponentRegistration>();
24  
25      private Log log = LogFactory.getLog(DefaultComponentRegistrar.class);
26  
27      public InstanceBuilder register(Class<?>... mainInterfaces)
28      {
29          Registration reg = new Registration(mainInterfaces);
30          registry.add(reg);
31          return new DefaultInstanceBuilder(reg);
32      }
33  
34      public List<ServiceRegistration> writeRegistry(BundleContext ctx)
35      {
36          ArrayList<ServiceRegistration> services = new ArrayList<ServiceRegistration>();
37  
38          for (HostComponentRegistration reg : registry)
39          {
40              String[] names = reg.getMainInterfaces();
41  
42              reg.getProperties().put(HOST_COMPONENT_FLAG, Boolean.TRUE.toString());
43  
44              if (log.isDebugEnabled())
45                  log.debug("Registering: "+ Arrays.asList(names)+" instance "+reg.getInstance() + "with properties: "+reg.getProperties());
46  
47              ServiceRegistration sreg = ctx.registerService(names, wrapService(reg.getMainInterfaceClasses(), reg.getInstance()), reg.getProperties());
48              if (sreg != null)
49              {
50                  services.add(sreg);
51              }
52          }
53          return services;
54      }
55  
56      /**
57       * Wraps the service in a dynamic proxy that ensures all methods are executed with the object class's class loader
58       * as the context class loader
59       * @param interfaces The interfaces to proxy
60       * @param service The instance to proxy
61       * @return A proxy that wraps the service
62       */
63      protected Object wrapService(Class[] interfaces, final Object service)
64      {
65          final Object wrappedService = Proxy.newProxyInstance(
66              getClass().getClassLoader(),
67              interfaces,
68              new InvocationHandler() {
69                  public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
70                      final Thread thread = Thread.currentThread();
71                      final ClassLoader ccl = thread.getContextClassLoader();
72                      try {
73                          thread.setContextClassLoader(service.getClass().getClassLoader());
74                          return method.invoke(service, objects);
75                      } catch (InvocationTargetException e) {
76                          throw e.getTargetException();
77                      } finally {
78                          thread.setContextClassLoader(ccl);
79                      }
80                  }
81              }
82          );
83          return wrappedService;
84      }
85  
86      public List<HostComponentRegistration> getRegistry()
87      {
88          return registry;
89      }
90  }