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