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
28
29
30
31
32
33
34 package info.magnolia.objectfactory.guice;
35
36 import info.magnolia.module.model.ComponentDefinition;
37 import info.magnolia.objectfactory.ComponentFactory;
38 import info.magnolia.objectfactory.annotation.LazySingleton;
39 import info.magnolia.objectfactory.annotation.LocalScoped;
40 import info.magnolia.objectfactory.annotation.SessionScoped;
41 import info.magnolia.objectfactory.configuration.ComponentConfiguration;
42 import info.magnolia.objectfactory.configuration.ComponentProviderConfiguration;
43 import info.magnolia.objectfactory.configuration.ConfiguredComponentConfiguration;
44 import info.magnolia.objectfactory.configuration.ImplementationConfiguration;
45 import info.magnolia.objectfactory.configuration.InstanceConfiguration;
46 import info.magnolia.objectfactory.configuration.ProviderConfiguration;
47
48 import java.lang.annotation.Annotation;
49 import java.util.Map;
50
51 import javax.inject.Provider;
52 import javax.inject.Singleton;
53
54 import com.google.inject.util.Providers;
55 import org.apache.commons.lang.StringUtils;
56
57 import com.google.inject.AbstractModule;
58 import com.google.inject.Module;
59 import com.google.inject.binder.ScopedBindingBuilder;
60
61
62
63
64
65
66
67 public class GuiceComponentConfigurationModule extends AbstractModule {
68
69 private final ComponentProviderConfiguration configuration;
70
71 public GuiceComponentConfigurationModule(ComponentProviderConfiguration configuration) {
72 this.configuration = configuration;
73 }
74
75 @Override
76 protected void configure() {
77
78 for (Map.Entry<Class, ComponentConfiguration> entry : configuration.getComponents().entrySet()) {
79 bindConfiguration(entry.getValue());
80 }
81
82 for (Object configurer : configuration.getConfigurers()) {
83 if (configurer instanceof Module) {
84 install((Module) configurer);
85 }
86 }
87 }
88
89 private <T> void bindConfiguration(ComponentConfiguration<T> configuration) {
90 if (configuration instanceof ImplementationConfiguration) {
91 bindImplementation((ImplementationConfiguration<T>) configuration);
92 } else if (configuration instanceof InstanceConfiguration) {
93 bindInstance((InstanceConfiguration<T>) configuration);
94 } else if (configuration instanceof ProviderConfiguration) {
95 bindProvider((ProviderConfiguration<T>) configuration);
96 } else if (configuration instanceof ConfiguredComponentConfiguration) {
97 ConfiguredComponentConfiguration<T> configured = (ConfiguredComponentConfiguration<T>) configuration;
98 if (configured.isObserved()) {
99 bindObservedComponent(configured);
100 } else {
101 bindConfiguredComponent(configured);
102 }
103 } else {
104 throw new IllegalStateException("Component configuration is ambiguous for component with type [" + configuration.getType() + "]");
105 }
106 }
107
108 private <T> void bindConfiguredComponent(ConfiguredComponentConfiguration<T> configuration) {
109 Provider<T> provider = new GuiceConfiguredComponentProvider<T>(configuration.getWorkspace(), configuration.getPath());
110 ScopedBindingBuilder builder = bindProvider(configuration.getType(), provider);
111 bindInScope(builder, configuration);
112 }
113
114 private <T> void bindObservedComponent(ConfiguredComponentConfiguration<T> configuration) {
115 Class<T> key = configuration.getType();
116 Provider<T> provider = new GuiceObservedComponentProvider<T>(configuration.getWorkspace(), configuration.getPath(), key);
117 ScopedBindingBuilder builder = bindProvider(configuration.getType(), provider);
118 bindInScope(builder, configuration);
119 }
120
121 private <T> void bindProvider(ProviderConfiguration<T> configuration) {
122 Class<?> factoryClass = configuration.getProviderClass();
123
124 if (ComponentFactory.class.isAssignableFrom(factoryClass)) {
125 Provider<T> provider = GuiceUtils.providerForComponentFactory((Class<? extends ComponentFactory<T>>) factoryClass);
126 ScopedBindingBuilder builder = bindProvider(configuration.getType(), provider);
127 bindInScope(builder, configuration);
128 } else if (Provider.class.isAssignableFrom(factoryClass)) {
129 ScopedBindingBuilder builder = bindProvider(configuration.getType(), (Class<? extends Provider<T>>) factoryClass);
130 bindInScope(builder, configuration);
131 } else {
132 throw new IllegalStateException("Unsupported provider class [" + factoryClass + "] for component with type [" + configuration.getType() + "]");
133 }
134 }
135
136 private <T> void bindInstance(InstanceConfiguration<T> configuration) {
137 Class<T> key = configuration.getType();
138 Object instance = configuration.getInstance();
139 if (instance instanceof Provider) {
140 bindProvider(configuration.getType(), (Provider<T>) instance);
141 } else if (instance instanceof ComponentFactory) {
142 bindProvider(configuration.getType(), GuiceUtils.providerForComponentFactory((ComponentFactory<T>) instance));
143 } else {
144 bind(key).toInstance((T) instance);
145 }
146
147 }
148
149 private <T> void bindImplementation(ImplementationConfiguration<T> configuration) {
150 Class<T> key = configuration.getType();
151 Class<? extends T> implementation = configuration.getImplementation();
152
153 ScopedBindingBuilder builder;
154 if (key.equals(implementation)) {
155 builder = bind(implementation);
156 } else {
157 builder = bind(key).to(implementation);
158 }
159 bindInScope(builder, configuration);
160 }
161
162 private <T> ScopedBindingBuilder bindProvider(Class<T> type, Provider<T> provider) {
163 return bind(type).toProvider(Providers.guicify(provider));
164 }
165
166 private <T> ScopedBindingBuilder bindProvider(Class<T> type, Class<? extends Provider<T>> provider) {
167 return bind(type).toProvider(provider);
168 }
169
170 private <T> void bindInScope(ScopedBindingBuilder builder, ComponentConfiguration<T> configuration) {
171 Class<? extends Annotation> scopeAnnotation = getScope(configuration);
172 if (scopeAnnotation != null) {
173 builder.in(scopeAnnotation);
174 }
175 }
176
177 private Class<? extends Annotation> getScope(ComponentConfiguration<?> componentConfiguration) {
178 String scope = componentConfiguration.getScope();
179 if (StringUtils.isEmpty(scope)) {
180 return null;
181 }
182 if (ComponentDefinition.SCOPE_SINGLETON.equalsIgnoreCase(scope) && !componentConfiguration.isLazy()) {
183 return Singleton.class;
184 }
185 if (ComponentDefinition.SCOPE_SINGLETON.equalsIgnoreCase(scope) && componentConfiguration.isLazy()) {
186 return LazySingleton.class;
187 }
188 if (ComponentDefinition.SCOPE_LOCAL.equalsIgnoreCase(scope)) {
189 return LocalScoped.class;
190 }
191 if (ComponentDefinition.SCOPE_SESSION.equalsIgnoreCase(scope)) {
192 return SessionScoped.class;
193 }
194 throw new IllegalStateException("Unknown scope [" + scope + "] for component with type [" + componentConfiguration.getType() + "]");
195 }
196 }