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.cms.core.SystemProperty;
37 import info.magnolia.objectfactory.ComponentProvider;
38 import info.magnolia.objectfactory.Components;
39 import info.magnolia.objectfactory.configuration.ComponentConfigurer;
40 import info.magnolia.objectfactory.configuration.ComponentProviderConfiguration;
41
42 import java.util.ArrayList;
43 import java.util.List;
44
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 import com.google.inject.AbstractModule;
49 import com.google.inject.CreationException;
50 import com.google.inject.Guice;
51 import com.google.inject.Injector;
52 import com.google.inject.Module;
53 import com.google.inject.Stage;
54 import com.google.inject.util.Modules;
55 import com.mycila.guice.ext.closeable.CloseableModule;
56 import com.mycila.guice.ext.jsr250.Jsr250Module;
57
58
59
60
61 public class GuiceComponentProviderBuilder {
62
63 private static final Logger log = LoggerFactory.getLogger(GuiceComponentProviderBuilder.class);
64 private ComponentProviderConfiguration configuration;
65 private boolean exposeGlobally;
66 private GuiceComponentProvider parent;
67 private final List<Module> extraModules = new ArrayList<Module>();
68 private Stage stage;
69
70 public GuiceComponentProviderBuilder exposeGlobally() {
71 this.exposeGlobally = true;
72 return this;
73 }
74
75 public GuiceComponentProviderBuilder withConfiguration(ComponentProviderConfiguration configuration) {
76 this.configuration = configuration;
77 return this;
78 }
79
80 public GuiceComponentProviderBuilder withParent(GuiceComponentProvider parent) {
81 this.parent = parent;
82 return this;
83 }
84
85 public GuiceComponentProviderBuilder inStage(Stage stage) {
86 this.stage = stage;
87 return this;
88 }
89
90 public void addModule(Module module) {
91 this.extraModules.add(module);
92 }
93
94 public GuiceComponentProvider build(ComponentConfigurer... configurers) {
95
96 if (configuration == null) {
97 configuration = new ComponentProviderConfiguration();
98 }
99
100
101 for (ComponentConfigurer configurer : configurers) {
102 configuration.addConfigurer(configurer);
103 }
104
105
106 for (ComponentConfigurer configurer : configuration.getConfigurers()) {
107 configurer.doWithConfiguration(parent, configuration);
108 }
109
110
111 final GuiceComponentProvider componentProvider = new GuiceComponentProvider(configuration.getTypeMapping(), parent);
112 if (exposeGlobally) {
113 Components.setComponentProvider(componentProvider);
114 }
115
116 Module module = new AbstractModule() {
117 @Override
118 protected void configure() {
119
120
121 bind(ComponentProvider.class).toInstance(componentProvider);
122
123
124 if (Boolean.valueOf(SystemProperty.getProperty("magnolia.jsr250.enabled", "true"))) {
125
126 install(new Jsr250Module());
127 }
128
129 install(new GuiceComponentConfigurationModule(configuration));
130
131 for (Module extraModule : extraModules) {
132 binder().install(extraModule);
133 }
134
135 install(new CloseableModule());
136 }
137 };
138
139 if (parent != null) {
140 GuiceParentBindingsModule parentBindingsModule = new GuiceParentBindingsModule(parent.getInjector());
141 module = Modules.override(parentBindingsModule).with(module);
142 }
143
144 try {
145 Injector injector = Guice.createInjector(resolveStageToUse(), module);
146 return (GuiceComponentProvider) injector.getInstance(ComponentProvider.class);
147 } catch (CreationException e) {
148 log.error("Magnolia failed to load module configuration with types {} and components {}. Please ensure you don't have any legacy modules present in your web application.", configuration.getTypeMapping(), configuration.getComponents(), e);
149 throw e;
150 }
151
152 }
153
154 public GuiceComponentProvider build() {
155 return build(new GuiceContextAndScopesConfigurer(), new GuicePropertyConfigurer());
156 }
157
158 private Stage resolveStageToUse() {
159 if (stage != null) {
160 return stage;
161 }
162 if (parent != null) {
163 return parent.getInjector().getInstance(Stage.class);
164 }
165 return Stage.PRODUCTION;
166 }
167 }