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 private final Map<Class<?>, Object> context;
24
25 public SimpleConstructorHostContainer(final Map<Class<?>, Object> context) {
26 final Map<Class<?>, Object> tmp = new HashMap<>(context);
27 tmp.put(HostContainer.class, this);
28 this.context = Collections.unmodifiableMap(tmp);
29 }
30
31
32
33
34
35
36
37
38 public <T> T create(final Class<T> moduleClass) throws IllegalArgumentException {
39 for (final Constructor<T> constructor : findConstructorsLargestFirst(moduleClass)) {
40 final List<Object> params = new ArrayList<>();
41 for (final Class<?> paramType : constructor.getParameterTypes()) {
42 if (context.containsKey(paramType)) {
43 params.add(context.get(paramType));
44 }
45 }
46 if (constructor.getParameterTypes().length != params.size()) {
47 continue;
48 }
49
50 try {
51 return constructor.newInstance(params.toArray());
52 } catch (final InstantiationException e) {
53 throw new IllegalArgumentException(e);
54 } catch (final IllegalAccessException e) {
55 throw new IllegalArgumentException(e);
56 } catch (final InvocationTargetException e) {
57 throw new IllegalArgumentException(e);
58 }
59 }
60
61 throw new IllegalArgumentException("Unable to match any constructor for class " + moduleClass);
62 }
63
64 @SuppressWarnings("unchecked")
65 private <T> Collection<Constructor<T>> findConstructorsLargestFirst(final Class<T> moduleClass) {
66 final Set<Constructor<T>> constructors = new TreeSet<Constructor<T>>(new Comparator<Constructor<T>>() {
67 public int compare(final Constructor<T> first, final Constructor<T> second) {
68
69 return Integer.valueOf(second.getParameterTypes().length).compareTo(first.getParameterTypes().length);
70 }
71 });
72 for (final Constructor<?> constructor : moduleClass.getConstructors()) {
73 constructors.add((Constructor<T>) constructor);
74 }
75 return constructors;
76 }
77 }