blob: b83416435f4869e23fdccb6c7f7eda8e235d5288 [file] [log] [blame]
kevinb9nb20cc352007-03-01 19:35:41 +00001/*
2 * Copyright (C) 2007 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
kevinb9ndb85d9c2007-02-20 05:23:46 +000017package com.google.inject;
18
limpbizkit5a72c092008-05-18 02:25:11 +000019import com.google.inject.commands.*;
20import com.google.inject.internal.UniqueAnnotations;
21
kevinb9ndb85d9c2007-02-20 05:23:46 +000022import java.util.Arrays;
limpbizkit5a72c092008-05-18 02:25:11 +000023import java.util.HashSet;
24import java.util.List;
25import java.util.Set;
kevinb9ndb85d9c2007-02-20 05:23:46 +000026
27/**
kevinb9na2915a92007-02-28 06:20:30 +000028 * The entry point to the Guice framework. Creates {@link Injector}s from
crazyboblee0bfdbc62007-02-20 21:47:19 +000029 * {@link Module}s.
kevinb9nb950ad92007-03-13 02:16:16 +000030 *
31 * <p>Guice supports a model of development that draws clear boundaries between
32 * APIs, Implementations of these APIs, Modules which configure these
33 * implementations, and finally Applications which consist of a collection of
34 * Modules. It is the Application, which typically defines your {@code main()}
35 * method, that bootstraps the Guice Injector using the {@code Guice} class, as
36 * in this example:
37 * <pre>
38 * public class FooApplication {
39 * public static void main(String[] args) {
40 * Injector injector = Guice.createInjector(
41 * new ModuleA(),
42 * new ModuleB(),
43 * . . .
44 * new FooApplicationFlagsModule(args)
45 * );
46 *
47 * // Now just bootstrap the application and you're done
48 * MyStartClass starter = injector.getInstance(MyStartClass.class);
49 * starter.runApplication();
50 * }
51 * }
52 * </pre>
kevinb9ndb85d9c2007-02-20 05:23:46 +000053 */
kevinb9ne5073a22007-02-20 18:06:47 +000054public final class Guice {
kevinb9ndb85d9c2007-02-20 05:23:46 +000055
crazyboblee0bfdbc62007-02-20 21:47:19 +000056 private Guice() {}
57
58 /**
kevinb9na2915a92007-02-28 06:20:30 +000059 * Creates an injector for the given set of modules.
crazybobleec1d0c642007-03-07 17:20:22 +000060 *
kevinb9nb950ad92007-03-13 02:16:16 +000061 * @throws CreationException if one or more errors occur during Injector
62 * construction
crazyboblee0bfdbc62007-02-20 21:47:19 +000063 */
crazybobleec1d0c642007-03-07 17:20:22 +000064 public static Injector createInjector(Module... modules) {
kevinb9na2915a92007-02-28 06:20:30 +000065 return createInjector(Arrays.asList(modules));
kevinb9ndb85d9c2007-02-20 05:23:46 +000066 }
67
crazyboblee0bfdbc62007-02-20 21:47:19 +000068 /**
kevinb9na2915a92007-02-28 06:20:30 +000069 * Creates an injector for the given set of modules.
crazybobleec1d0c642007-03-07 17:20:22 +000070 *
kevinb9nb950ad92007-03-13 02:16:16 +000071 * @throws CreationException if one or more errors occur during Injector
72 * construction
crazyboblee0bfdbc62007-02-20 21:47:19 +000073 */
crazybobleed9d16a02007-09-09 21:18:48 +000074 public static Injector createInjector(Iterable<? extends Module> modules) {
kevinb9na2915a92007-02-28 06:20:30 +000075 return createInjector(Stage.DEVELOPMENT, modules);
kevinb9ne5073a22007-02-20 18:06:47 +000076 }
77
crazyboblee0bfdbc62007-02-20 21:47:19 +000078 /**
kevinb9na2915a92007-02-28 06:20:30 +000079 * Creates an injector for the given set of modules, in a given development
80 * stage.
crazybobleec1d0c642007-03-07 17:20:22 +000081 *
kevinb9nb950ad92007-03-13 02:16:16 +000082 * @throws CreationException if one or more errors occur during Injector
83 * construction
crazyboblee0bfdbc62007-02-20 21:47:19 +000084 */
crazybobleec1d0c642007-03-07 17:20:22 +000085 public static Injector createInjector(Stage stage, Module... modules) {
kevinb9na2915a92007-02-28 06:20:30 +000086 return createInjector(stage, Arrays.asList(modules));
kevinb9ne5073a22007-02-20 18:06:47 +000087 }
88
crazyboblee0bfdbc62007-02-20 21:47:19 +000089 /**
kevinb9na2915a92007-02-28 06:20:30 +000090 * Creates an injector for the given set of modules, in a given development
91 * stage.
crazybobleec1d0c642007-03-07 17:20:22 +000092 *
kevinb9nb950ad92007-03-13 02:16:16 +000093 * @throws CreationException if one or more errors occur during Injector
94 * construction
crazyboblee0bfdbc62007-02-20 21:47:19 +000095 */
crazybobleed9d16a02007-09-09 21:18:48 +000096 public static Injector createInjector(Stage stage,
97 Iterable<? extends Module> modules) {
dan.halem5d187432008-02-22 22:52:28 +000098 return createInjector(null, stage, modules);
99 }
100
101
102 /**
103 * Creates an injector for the given set of modules, with the given parent
104 * injector.
105 *
106 * @throws CreationException if one or more errors occur during Injector
107 * construction
108 */
109 public static Injector createInjector(Injector parent,
110 Iterable<? extends Module> modules) {
111 return createInjector(parent, Stage.DEVELOPMENT, modules);
112 }
113
114
115 /**
116 * Creates an injector for the given set of modules, with the given parent
117 * injector.
118 *
119 * @throws CreationException if one or more errors occur during Injector
120 * construction
121 */
122 public static Injector createInjector(Injector parent,
123 Module... modules) {
124 return createInjector(parent, Stage.DEVELOPMENT, Arrays.asList(modules));
125 }
126
127 /**
128 * Creates an injector for the given set of modules, in a given development
129 * stage, with the given parent injector.
130 *
131 * @throws CreationException if one or more errors occur during Injector
132 * construction
133 */
134 public static Injector createInjector(
135 Injector parent, Stage stage,
136 Iterable<? extends Module> modules) {
limpbizkit3d58d6b2008-03-08 16:11:47 +0000137 return new InjectorBuilder()
138 .stage(stage)
139 .parentInjector(parent)
140 .addModules(modules)
141 .build();
kevinb9ndb85d9c2007-02-20 05:23:46 +0000142 }
dan.halem5d187432008-02-22 22:52:28 +0000143
limpbizkit5a72c092008-05-18 02:25:11 +0000144 /**
145 * Returns a new {@link Module} that overlays {@code overridesModule} over
146 * {@code module}. If a key is bound by both modules, only the binding in
147 * overrides is kept. This can be used to replace bindings in a production
148 * module with test bindings:
149 * <pre>
150 * Module functionalTestModule
151 * = Guice.overrideModule(new ProductionModule(), new TestModule());
152 * </pre>
153 */
154 public static Module overrideModule(Module module, Module overridesModule) {
155 final FutureInjector futureInjector = new FutureInjector();
156 CommandRecorder commandRecorder = new CommandRecorder(futureInjector);
157 final List<Command> commands = commandRecorder.recordCommands(module);
158 final List<Command> overrideCommands = commandRecorder.recordCommands(overridesModule);
159
160 return new AbstractModule() {
161 public void configure() {
162 final Set<Key> overriddenKeys = new HashSet<Key>();
163
164 bind(Object.class).annotatedWith(UniqueAnnotations.create())
165 .toInstance(new Object() {
166 @Inject void initialize(Injector injector) {
167 futureInjector.initialize(injector);
168 }
169 });
170
171 // execute the overrides module, keeping track of which keys were bound
172 new CommandReplayer() {
173 @Override public <T> void replayBind(Binder binder, BindCommand<T> command) {
174 overriddenKeys.add(command.getKey());
175 super.replayBind(binder, command);
176 }
177 @Override public void replayBindConstant(Binder binder, BindConstantCommand command) {
178 overriddenKeys.add(command.getKey());
179 super.replayBindConstant(binder, command);
180 }
181 }.replay(binder(), overrideCommands);
182
183 // bind the regular module, skipping overridden keys. We only skip each
184 // overridden key once, so things still blow up if the module binds the
185 // same key multiple times
186 new CommandReplayer() {
187 @Override public <T> void replayBind(Binder binder, BindCommand<T> command) {
188 if (!overriddenKeys.remove(command.getKey())) {
189 super.replayBind(binder, command);
190 }
191 }
192 @Override public void replayBindConstant(Binder binder, BindConstantCommand command) {
193 if (!overriddenKeys.remove(command.getKey())) {
194 super.replayBindConstant(binder, command);
195 }
196 }
197 }.replay(binder(), commands);
198
199 // TODO: bind the overridden keys using multibinder
200 }
201 };
202 }
kevinb9ndb85d9c2007-02-20 05:23:46 +0000203}