1 package com.atlassian.plugin.refimpl;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationHandler;
5 import java.lang.reflect.InvocationTargetException;
6 import java.lang.reflect.Method;
7 import java.lang.reflect.Proxy;
8 import java.util.ArrayList;
9 import java.util.Collection;
10 import java.util.Comparator;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14 import java.util.TreeSet;
15 import java.util.concurrent.ConcurrentHashMap;
16
17 import org.osgi.util.tracker.ServiceTracker;
18
19 import com.atlassian.plugin.hostcontainer.HostContainer;
20 import com.atlassian.plugin.osgi.container.OsgiContainerManager;
21
22
23
24
25 class RefimplHostContainer implements HostContainer
26 {
27 private final Map<Class<?>, Object> context;
28 private final OsgiContainerManager osgiContainer;
29
30 public RefimplHostContainer(Map<Class<?>, Object> context, OsgiContainerManager osgiContainer)
31 {
32 this.context = new ConcurrentHashMap<Class<?>, Object>(context);
33 context.put(HostContainer.class, this);
34
35 this.osgiContainer = osgiContainer;
36 }
37
38
39
40
41
42
43
44
45 public <T> T create(final Class<T> moduleClass) throws IllegalArgumentException
46 {
47 for (final Constructor<T> constructor : findConstructorsLargestFirst(moduleClass))
48 {
49 final List<Object> params = new ArrayList<Object>();
50 for (final Class<?> paramType : constructor.getParameterTypes())
51 {
52 final ServiceTracker tracker = osgiContainer.getServiceTracker(paramType.getName());
53 if (tracker == null)
54 {
55 continue;
56 }
57 tracker.open();
58 Object serviceProxy = Proxy.newProxyInstance(paramType.getClassLoader(), new Class<?>[] { paramType }, new InvocationHandler()
59 {
60 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
61 {
62 return method.invoke(tracker.getService(), args);
63 }
64 });
65 params.add(serviceProxy);
66 }
67 if (constructor.getParameterTypes().length != params.size())
68 {
69 continue;
70 }
71
72 try
73 {
74 return constructor.newInstance(params.toArray());
75 }
76 catch (final InstantiationException e)
77 {
78 throw new IllegalArgumentException(e);
79 }
80 catch (final IllegalAccessException e)
81 {
82 throw new IllegalArgumentException(e);
83 }
84 catch (final InvocationTargetException e)
85 {
86 throw new IllegalArgumentException(e);
87 }
88 }
89
90 throw new IllegalArgumentException("Unable to match any constructor for class " + moduleClass);
91 }
92
93
94
95
96
97
98
99 @SuppressWarnings("unchecked")
100 public <T> T getInstance(final Class<T> moduleClass)
101 {
102 return (T) context.get(moduleClass);
103 }
104
105 @SuppressWarnings("unchecked")
106 private <T> Collection<Constructor<T>> findConstructorsLargestFirst(final Class<T> moduleClass)
107 {
108 final Set<Constructor<T>> constructors = new TreeSet<Constructor<T>>(new Comparator<Constructor<T>>()
109 {
110 public int compare(final Constructor<T> first, final Constructor<T> second)
111 {
112
113 return Integer.valueOf(second.getParameterTypes().length).compareTo(first.getParameterTypes().length);
114 }
115 });
116 for (final Constructor<?> constructor : moduleClass.getConstructors())
117 {
118 constructors.add((Constructor<T>) constructor);
119 }
120 return constructors;
121 }
122 }