1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package com.lhkbob.entreri.impl;
28
29 import com.lhkbob.entreri.Component;
30
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.InvocationTargetException;
33 import java.lang.reflect.ParameterizedType;
34 import java.lang.reflect.Type;
35
36
37
38
39
40
41
42
43 class CompiledFactoryProvider extends ComponentFactoryProvider {
44 @Override
45 public <T extends Component> Factory<T> getFactory(Class<T> componentType) {
46 try {
47 return new CompiledFactory<>(componentType);
48 } catch (ClassNotFoundException cfe) {
49
50
51 return null;
52 }
53 }
54
55 private static class CompiledFactory<T extends Component> implements Factory<T> {
56 final Class<? extends AbstractComponent<T>> implType;
57 final ComponentSpecification specification;
58
59 final Constructor<? extends AbstractComponent<T>> ctor;
60
61 @SuppressWarnings("unchecked")
62 public CompiledFactory(Class<T> type) throws ClassNotFoundException {
63 specification = ComponentSpecification.Factory.fromClass(type);
64 String implName = ComponentFactoryProvider
65 .getImplementationClassName(specification, true);
66
67 Class<?> loaded = Class.forName(implName);
68
69
70
71
72 if (!loaded.getSuperclass().equals(AbstractComponent.class)) {
73 throw new IllegalStateException(
74 "Discovered impl. class does not extend AbstractComponent for " +
75 type);
76 }
77 Type paramType = ((ParameterizedType) loaded.getGenericSuperclass())
78 .getActualTypeArguments()[0];
79 if (!paramType.equals(type)) {
80 throw new IllegalStateException(
81 "Discovered impl. uses wrong type parameter for AbstractComponent, was " +
82 paramType + " instead of " + type);
83 }
84 if (!type.isAssignableFrom(loaded)) {
85 throw new IllegalStateException(
86 "Discovered impl. does not implement the expected interface: " +
87 type);
88 }
89
90
91 implType = (Class<? extends AbstractComponent<T>>) loaded;
92
93 try {
94 ctor = implType.getConstructor(ComponentRepository.class);
95 } catch (NoSuchMethodException e) {
96 throw new IllegalStateException(
97 "Discovered impl. does not have mandated constructor for component: " +
98 type);
99 }
100 }
101
102
103 @Override
104 public AbstractComponent<T> newInstance(ComponentRepository<T> forRepository) {
105 try {
106 return ctor.newInstance(forRepository);
107 } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
108 throw new RuntimeException(
109 "Exception instantiating compiled component impl", e);
110 }
111 }
112
113 @Override
114 public ComponentSpecification getSpecification() {
115 return specification;
116 }
117 }
118 }