1 package com.atlassian.plugin.hostcontainer;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationTargetException;
5 import java.util.ArrayList;
6 import java.util.Collection;
7 import java.util.Collections;
8 import java.util.Comparator;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13 import java.util.TreeSet;
14
15
16
17
18
19
20
21
22 public class SimpleConstructorHostContainer implements HostContainer
23 {
24 private final Map<Class<?>, Object> context;
25
26 public SimpleConstructorHostContainer(final Map<Class<?>, Object> context)
27 {
28 final Map<Class<?>, Object> tmp = new HashMap<Class<?>, Object>(context);
29 tmp.put(HostContainer.class, this);
30 this.context = Collections.unmodifiableMap(tmp);
31 }
32
33
34
35
36
37
38
39
40 public <T> T create(final Class<T> moduleClass) throws IllegalArgumentException
41 {
42 for (final Constructor<T> constructor : findConstructorsLargestFirst(moduleClass))
43 {
44 final List<Object> params = new ArrayList<Object>();
45 for (final Class<?> paramType : constructor.getParameterTypes())
46 {
47 if (context.containsKey(paramType))
48 {
49 params.add(context.get(paramType));
50 }
51 }
52 if (constructor.getParameterTypes().length != params.size())
53 {
54 continue;
55 }
56
57 try
58 {
59 return constructor.newInstance(params.toArray());
60 }
61 catch (final InstantiationException e)
62 {
63 throw new IllegalArgumentException(e);
64 }
65 catch (final IllegalAccessException e)
66 {
67 throw new IllegalArgumentException(e);
68 }
69 catch (final InvocationTargetException e)
70 {
71 throw new IllegalArgumentException(e);
72 }
73 }
74
75 throw new IllegalArgumentException("Unable to match any constructor for class " + moduleClass);
76 }
77
78
79
80
81
82
83
84 @SuppressWarnings("unchecked")
85 public <T> T getInstance(final Class<T> moduleClass)
86 {
87 return (T) context.get(moduleClass);
88 }
89
90 @SuppressWarnings("unchecked")
91 private <T> Collection<Constructor<T>> findConstructorsLargestFirst(final Class<T> moduleClass)
92 {
93 final Set<Constructor<T>> constructors = new TreeSet<Constructor<T>>(new Comparator<Constructor<T>>()
94 {
95 public int compare(final Constructor<T> first, final Constructor<T> second)
96 {
97
98 return Integer.valueOf(second.getParameterTypes().length).compareTo(first.getParameterTypes().length);
99 }
100 });
101 for (final Constructor<?> constructor : moduleClass.getConstructors())
102 {
103 constructors.add((Constructor<T>) constructor);
104 }
105 return constructors;
106 }
107 }