{
29 |
30 | /**
31 | * Injects dependencies into the fields and methods of {@code instance}.
32 | * Ignores the presence or absence of an injectable constructor.
33 | *
34 | * Whenever the object graph creates an instance, it performs this
35 | * injection automatically (after first performing constructor injection), so
36 | * if you're able to let the object graph create all your objects for you,
37 | * you'll never need to use this method.
38 | *
39 | * @param instance to inject members on. May be {@code null}.
40 | */
41 | void injectMembers(T instance);
42 | }
43 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/Provides.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 Google Inc.
3 | * Copyright (C) 2012 Square, Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger;
18 |
19 | import java.lang.annotation.Documented;
20 | import java.lang.annotation.Retention;
21 | import java.lang.annotation.Target;
22 |
23 | import static java.lang.annotation.ElementType.METHOD;
24 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
25 |
26 | /**
27 | * Annotates methods of a module to create a provider method binding. The
28 | * method's return type is bound to its returned value. The object graph will
29 | * pass dependencies to the method as parameters.
30 | *
31 | * @author Bob Lee
32 | */
33 | @Documented @Target(METHOD) @Retention(RUNTIME)
34 | public @interface Provides {
35 | /** The type of binding into which the return type of the annotated method contributes. */
36 | enum Type {
37 | /**
38 | * The method is the only one which can produce the value for the specified return type. This
39 | * is the default behavior.
40 | */
41 | UNIQUE,
42 |
43 | /**
44 | * The method's return type forms the generic type argument of a {@code Set}, and the
45 | * returned value is contributed to the set. The object graph will pass dependencies to the
46 | * method as parameters. The {@code Set} produced from the accumulation of values will be
47 | * immutable.
48 | */
49 | SET,
50 |
51 | /**
52 | * Like {@link #SET}, except the method's return type is {@code Set}, where any values are
53 | * contributed to the set. An example use is to provide a default empty set binding, which is
54 | * otherwise not possible using {@link #SET}.
55 | */
56 | SET_VALUES;
57 | }
58 |
59 | Type type() default Type.UNIQUE;
60 | }
61 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/BindingsGroup.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
3 | * Copyright (C) 2013 Google, Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger.internal;
18 |
19 | import java.util.LinkedHashMap;
20 | import java.util.Map;
21 | import java.util.Map.Entry;
22 | import java.util.Set;
23 |
24 | /**
25 | * A grouping of bindings that fails when existing values are clobbered, to be used in collecting
26 | * the initial set of bindings for a graph (from provides methods).
27 | */
28 | public abstract class BindingsGroup {
29 | private final Map> bindings = new LinkedHashMap>();
30 |
31 | public abstract Binding> contributeSetBinding(String key, SetBinding> value);
32 |
33 | public Binding> contributeProvidesBinding(String key, ProvidesBinding> value) {
34 | return put(key, value);
35 | }
36 |
37 | protected Binding> put(String key, Binding> value) {
38 | Binding> clobbered = bindings.put(key, value);
39 | if (clobbered != null) {
40 | bindings.put(key, clobbered); // Put things back as they were.
41 | throw new IllegalArgumentException("Duplicate:\n " + clobbered + "\n " + value);
42 | }
43 | return null;
44 | }
45 |
46 | public Binding> get(String key) {
47 | return bindings.get(key);
48 | }
49 |
50 | public final Set>> entrySet() {
51 | return bindings.entrySet();
52 | }
53 |
54 | @Override public String toString() {
55 | return getClass().getSimpleName() + bindings.toString();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/BuiltInBinding.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Square, 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 | package dagger.internal;
17 |
18 |
19 | /**
20 | * Injects a Provider or a MembersInjector.
21 | */
22 | final class BuiltInBinding extends Binding {
23 | private final String delegateKey;
24 | private final ClassLoader classLoader;
25 | private Binding> delegate;
26 |
27 | public BuiltInBinding(
28 | String key, Object requiredBy, ClassLoader classLoader, String delegateKey) {
29 | super(key, null, false, requiredBy);
30 | this.classLoader = classLoader;
31 | this.delegateKey = delegateKey;
32 | }
33 |
34 | @Override public void attach(Linker linker) {
35 | delegate = linker.requestBinding(delegateKey, requiredBy, classLoader);
36 | }
37 |
38 | @Override public void injectMembers(T t) {
39 | throw new UnsupportedOperationException();
40 | }
41 |
42 | @SuppressWarnings("unchecked") // At runtime we know 'T' is a Provider or MembersInjector.
43 | @Override public T get() {
44 | return (T) delegate;
45 | }
46 |
47 | public Binding> getDelegate() {
48 | return delegate;
49 | }
50 |
51 | // public void getDependencies() not overridden.
52 | // We don't add 'delegate' because it isn't actually used by get() or injectMembers().
53 | }
54 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/LazyBinding.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Google, Inc.
3 | * Copyright (C) 2012 Square, Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger.internal;
18 |
19 | import dagger.Lazy;
20 |
21 | /**
22 | * Injects a Lazy wrapper for a type T
23 | */
24 | final class LazyBinding extends Binding> {
25 |
26 | final static Object NOT_PRESENT = new Object();
27 |
28 | private final String lazyKey;
29 | private final ClassLoader loader;
30 | Binding delegate;
31 |
32 | LazyBinding(String key, Object requiredBy, ClassLoader loader, String lazyKey) {
33 | super(key, null, false, requiredBy);
34 | this.loader = loader;
35 | this.lazyKey = lazyKey;
36 | }
37 |
38 | @SuppressWarnings("unchecked") // At runtime we know it's a Binding>.
39 | @Override
40 | public void attach(Linker linker) {
41 | delegate = (Binding) linker.requestBinding(lazyKey, requiredBy, loader);
42 | }
43 |
44 | @Override public void injectMembers(Lazy t) {
45 | throw new UnsupportedOperationException(); // Injecting into a custom Lazy not supported.
46 | }
47 |
48 | @Override
49 | public Lazy get() {
50 | return new Lazy() {
51 | private volatile Object cacheValue = NOT_PRESENT;
52 |
53 | @SuppressWarnings("unchecked") // Delegate is of type T
54 | @Override
55 | public T get() {
56 | if (cacheValue == NOT_PRESENT) {
57 | synchronized (this) {
58 | if (cacheValue == NOT_PRESENT) {
59 | cacheValue = delegate.get();
60 | }
61 | }
62 | }
63 | return (T) cacheValue;
64 | }
65 | };
66 | }
67 |
68 | // public void getDependencies() not overridden.
69 | // We don't add 'delegate' because it isn't actually used by get() or injectMembers().
70 | }
71 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/Memoizer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 The Android Open Source Project
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 | package dagger.internal;
17 |
18 | import java.util.LinkedHashMap;
19 | import java.util.Map;
20 | import java.util.concurrent.locks.Lock;
21 | import java.util.concurrent.locks.ReadWriteLock;
22 | import java.util.concurrent.locks.ReentrantReadWriteLock;
23 |
24 | /**
25 | * Represents an operation whose results are memoized. Results returned by invocations of
26 | * {@link #create(Object)} are memoized so that the same object is returned for multiple invocations
27 | * of {@link #get(Object)} for the same key.
28 | */
29 | abstract class Memoizer {
30 | private final Map map;
31 | private final Lock readLock;
32 | private final Lock writeLock;
33 |
34 | public Memoizer() {
35 | this.map = new LinkedHashMap();
36 | ReadWriteLock lock = new ReentrantReadWriteLock();
37 | this.readLock = lock.readLock();
38 | this.writeLock = lock.writeLock();
39 | }
40 |
41 | public final V get(K key) {
42 | if (key == null) {
43 | throw new NullPointerException("key == null");
44 | }
45 |
46 | // check to see if we already have a value
47 | readLock.lock();
48 | try {
49 | V value = map.get(key);
50 | if (value != null) {
51 | return value;
52 | }
53 | } finally {
54 | readLock.unlock();
55 | }
56 |
57 | // create a new value. this may race and we might create more than one instance, but that's ok
58 | V newValue = create(key);
59 | if (newValue == null) {
60 | throw new NullPointerException("create returned null");
61 | }
62 |
63 | // write the new value and return it
64 | writeLock.lock();
65 | try {
66 | map.put(key, newValue);
67 | return newValue;
68 | } finally {
69 | writeLock.unlock();
70 | }
71 | }
72 |
73 | protected abstract V create(K key);
74 |
75 | @Override public final String toString() {
76 | readLock.lock();
77 | try {
78 | return map.toString();
79 | } finally {
80 | readLock.unlock();
81 | }
82 | }
83 | }
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/ModuleAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Square, Inc.
3 | * Copyright (C) 2012 Google, Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger.internal;
18 |
19 |
20 | /**
21 | * Extracts bindings from an {@code @Module}-annotated class.
22 | */
23 | public abstract class ModuleAdapter {
24 | public final Class moduleClass;
25 | public final String[] injectableTypes;
26 | public final Class>[] staticInjections;
27 | public final boolean overrides;
28 | public final Class>[] includes;
29 | public final boolean complete;
30 | public final boolean library;
31 |
32 | protected ModuleAdapter(Class moduleClass, String[] injectableTypes,
33 | Class>[] staticInjections, boolean overrides, Class>[] includes, boolean complete,
34 | boolean library) {
35 | this.moduleClass = moduleClass;
36 | this.injectableTypes = injectableTypes;
37 | this.staticInjections = staticInjections;
38 | this.overrides = overrides;
39 | this.includes = includes;
40 | this.complete = complete;
41 | this.library = library;
42 | }
43 |
44 | /**
45 | * Returns bindings for the {@code @Provides} methods of {@code module}. The
46 | * returned bindings must be linked before they can be used to inject values.
47 | */
48 | @SuppressWarnings("unused")
49 | public void getBindings(BindingsGroup map, T module) {
50 | // no-op;
51 | }
52 |
53 | /**
54 | * Returns a new instance of the module class created using a no-args
55 | * constructor. Only used when a manually-constructed module is not supplied.
56 | */
57 | protected T newModule() {
58 | throw new UnsupportedOperationException("No no-args constructor on " + getClass().getName());
59 | }
60 |
61 | @Override
62 | public final boolean equals(Object obj) {
63 | if (obj == this) {
64 | return true;
65 | } else if (obj instanceof ModuleAdapter>) {
66 | ModuleAdapter> that = (ModuleAdapter>) obj;
67 | return this.moduleClass.equals(that.moduleClass);
68 | } else {
69 | return false;
70 | }
71 | }
72 |
73 | @Override
74 | public final int hashCode() {
75 | return moduleClass.hashCode();
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/Modules.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Square, Inc.
3 | * Copyright (C) 2012 Google, Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger.internal;
18 |
19 |
20 | import java.util.LinkedHashMap;
21 | import java.util.Map;
22 |
23 | /**
24 | * Static helper for organizing modules.
25 | */
26 | public final class Modules {
27 |
28 | private Modules() { }
29 |
30 | /**
31 | * Returns a full set of module adapters, including module adapters for included
32 | * modules.
33 | */
34 | public static Map, Object> loadModules(Loader loader,
35 | Object[] seedModulesOrClasses) {
36 | Map, Object> seedAdapters =
37 | new LinkedHashMap, Object>(seedModulesOrClasses.length);
38 | for (int i = 0; i < seedModulesOrClasses.length; i++) {
39 | if (seedModulesOrClasses[i] instanceof Class>) {
40 | ModuleAdapter> adapter = loader.getModuleAdapter((Class>) seedModulesOrClasses[i]);
41 | seedAdapters.put(adapter, adapter.newModule());
42 | } else {
43 | ModuleAdapter> adapter = loader.getModuleAdapter(seedModulesOrClasses[i].getClass());
44 | seedAdapters.put(adapter, seedModulesOrClasses[i]);
45 | }
46 | }
47 |
48 | // Add the adapters that we have module instances for. This way we won't
49 | // construct module objects when we have a user-supplied instance.
50 | Map, Object> result =
51 | new LinkedHashMap, Object>(seedAdapters);
52 |
53 | // Next collect included modules
54 | Map, ModuleAdapter>> transitiveInclusions =
55 | new LinkedHashMap, ModuleAdapter>>();
56 | for (ModuleAdapter> adapter : seedAdapters.keySet()) {
57 | collectIncludedModulesRecursively(loader, adapter, transitiveInclusions);
58 | }
59 | // and create them if necessary
60 | for (ModuleAdapter> dependency : transitiveInclusions.values()) {
61 | if (!result.containsKey(dependency)) {
62 | result.put(dependency, dependency.newModule());
63 | }
64 | }
65 | return result;
66 | }
67 |
68 | /**
69 | * Fills {@code result} with the module adapters for the includes of {@code
70 | * adapter}, and their includes recursively.
71 | */
72 | private static void collectIncludedModulesRecursively(Loader plugin, ModuleAdapter> adapter,
73 | Map, ModuleAdapter>> result) {
74 | for (Class> include : adapter.includes) {
75 | if (!result.containsKey(include)) {
76 | ModuleAdapter> includedModuleAdapter = plugin.getModuleAdapter(include);
77 | result.put(include, includedModuleAdapter);
78 | collectIncludedModulesRecursively(plugin, includedModuleAdapter, result);
79 | }
80 | }
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/ProvidesBinding.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Google, Inc.
3 | * Copyright (C) 2013 Square, Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger.internal;
18 |
19 | /**
20 | * A {@code Binding} which delegates to a module method.
21 | */
22 | public abstract class ProvidesBinding extends Binding {
23 | protected final String moduleClass;
24 |
25 | protected final String methodName;
26 |
27 | /**
28 | * Creates a new {@code ProvidesBinding} with the given "provides" key, a flag as to whether
29 | * this binding should be scoped, and the requiredBy object for traceability.
30 | */
31 | public ProvidesBinding(String key, boolean singleton, String moduleClass, String methodName) {
32 | // Set requiredBy as fullMethodName to preserve older debugging meaning.
33 | super(key, null, singleton, moduleClass + "." + methodName + "()");
34 | this.moduleClass = moduleClass;
35 | this.methodName = methodName;
36 | }
37 |
38 | /**
39 | * A provides binding is responsible for implementing storage of the module instance, and
40 | * delegation to that module instance's method.
41 | */
42 | @Override
43 | public abstract T get();
44 |
45 | @Override public String toString() {
46 | return getClass().getName() + "[key=" + provideKey
47 | + " method=" + moduleClass + "." + methodName + "()" + "]";
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/StaticInjection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Square Inc.
3 | * Copyright (C) 2012 Google Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger.internal;
18 |
19 |
20 | /**
21 | * Injects the static fields of a class.
22 | */
23 | public abstract class StaticInjection {
24 |
25 | public abstract void attach(Linker linker);
26 |
27 | public abstract void inject();
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/ThrowingErrorHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Square, 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 | package dagger.internal;
17 |
18 | import java.util.List;
19 |
20 | /**
21 | * Handles errors by throwing an exception containing all the available errors.
22 | */
23 | public final class ThrowingErrorHandler implements Linker.ErrorHandler {
24 |
25 | @Override public void handleErrors(List errors) {
26 | if (errors.isEmpty()) {
27 | return;
28 | }
29 | StringBuilder message = new StringBuilder();
30 | message.append("Errors creating object graph:");
31 | for (String error : errors) {
32 | message.append("\n ").append(error);
33 | }
34 | throw new IllegalStateException(message.toString());
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/loaders/GeneratedAdapters.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
3 | * Copyright (C) 2013 Google, Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger.internal.loaders;
18 |
19 |
20 | /**
21 | * A single point for API used in common by Adapters and Adapter generators
22 | */
23 | public final class GeneratedAdapters {
24 | private static final String SEPARATOR = "$$";
25 | public static final String INJECT_ADAPTER_SUFFIX = SEPARATOR + "InjectAdapter";
26 | public static final String MODULE_ADAPTER_SUFFIX = SEPARATOR + "ModuleAdapter";
27 | public static final String STATIC_INJECTION_SUFFIX = SEPARATOR + "StaticInjection";
28 |
29 | private GeneratedAdapters() { }
30 | }
31 |
--------------------------------------------------------------------------------
/core/src/main/java/dagger/internal/loaders/ReflectiveStaticInjection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Square, 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 | package dagger.internal.loaders;
17 |
18 | import dagger.internal.Binding;
19 | import dagger.internal.Keys;
20 | import dagger.internal.Linker;
21 | import dagger.internal.StaticInjection;
22 | import java.lang.reflect.Field;
23 | import java.lang.reflect.Modifier;
24 | import java.util.ArrayList;
25 | import java.util.List;
26 | import javax.inject.Inject;
27 |
28 | /**
29 | * Uses reflection to inject the static fields of a class.
30 | */
31 | public final class ReflectiveStaticInjection extends StaticInjection {
32 | private final ClassLoader loader;
33 | private final Field[] fields;
34 | private Binding>[] bindings;
35 |
36 | private ReflectiveStaticInjection(ClassLoader loader, Field[] fields) {
37 | this.fields = fields;
38 | this.loader = loader;
39 | }
40 |
41 | @Override public void attach(Linker linker) {
42 | bindings = new Binding>[fields.length];
43 | for (int i = 0; i < fields.length; i++) {
44 | Field field = fields[i];
45 | String key = Keys.get(field.getGenericType(), field.getAnnotations(), field);
46 | bindings[i] = linker.requestBinding(key, field, loader);
47 | }
48 | }
49 |
50 | @Override public void inject() {
51 | try {
52 | for (int f = 0; f < fields.length; f++) {
53 | fields[f].set(null, bindings[f].get());
54 | }
55 | } catch (IllegalAccessException e) {
56 | throw new AssertionError(e);
57 | }
58 | }
59 |
60 | public static StaticInjection create(Class> injectedClass) {
61 | List fields = new ArrayList();
62 | for (Field field : injectedClass.getDeclaredFields()) {
63 | if (Modifier.isStatic(field.getModifiers()) && field.isAnnotationPresent(Inject.class)) {
64 | field.setAccessible(true);
65 | fields.add(field);
66 | }
67 | }
68 | if (fields.isEmpty()) {
69 | throw new IllegalArgumentException("No static injections: " + injectedClass.getName());
70 | }
71 | return new ReflectiveStaticInjection(injectedClass.getClassLoader(),
72 | fields.toArray(new Field[fields.size()]));
73 | }
74 | }
--------------------------------------------------------------------------------
/core/src/test/java/dagger/ExtensionWithStateTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Google Inc.
3 | * Copyright (C) 2013 Square Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger;
18 |
19 | import dagger.internal.TestingLoader;
20 | import javax.inject.Inject;
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 | import org.junit.runners.JUnit4;
24 |
25 | import static com.google.common.truth.Truth.assertThat;
26 |
27 | @RunWith(JUnit4.class)
28 | public final class ExtensionWithStateTest {
29 | static class A { }
30 |
31 | static class B {
32 | @Inject A a;
33 | }
34 |
35 | @Module(
36 | injects = A.class, // for testing
37 | complete = false
38 | )
39 | static class RootModule {
40 | final A a;
41 | RootModule(A a) {
42 | this.a = a;
43 | }
44 | @Provides A provideA() { return a; }
45 | }
46 |
47 | @Module(addsTo = RootModule.class, injects = { B.class })
48 | static class ExtensionModule { }
49 |
50 | @Test public void basicInjectionWithExtension() {
51 | A a = new A();
52 | ObjectGraph root = ObjectGraph.createWith(new TestingLoader(), new RootModule(a));
53 | assertThat(root.get(A.class)).isSameAs(a);
54 |
55 | // Extension graph behaves as the root graph would for root-ish things.
56 | ObjectGraph extension = root.plus(new ExtensionModule());
57 | assertThat(extension.get(A.class)).isSameAs(a);
58 | assertThat(extension.get(B.class).a).isSameAs(a);
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/core/src/test/java/dagger/ProblemDetectorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Square, 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 | package dagger;
17 |
18 | import dagger.internal.TestingLoader;
19 | import javax.inject.Inject;
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.junit.runners.JUnit4;
23 |
24 | import static org.junit.Assert.fail;
25 |
26 | @RunWith(JUnit4.class)
27 | public final class ProblemDetectorTest {
28 | @Test public void atInjectCircularDependenciesDetected() {
29 | class TestEntryPoint {
30 | @Inject Rock rock;
31 | }
32 |
33 | @Module(injects = TestEntryPoint.class)
34 | class TestModule {
35 | }
36 |
37 | ObjectGraph graph = ObjectGraph.createWith(new TestingLoader(), new TestModule());
38 | try {
39 | graph.validate();
40 | fail();
41 | } catch (RuntimeException expected) {
42 | }
43 | }
44 |
45 | @Test public void providesCircularDependenciesDetected() {
46 | @Module
47 | class TestModule {
48 | @Provides Integer provideInteger(String s) {
49 | throw new AssertionError();
50 | }
51 | @Provides String provideString(Integer i) {
52 | throw new AssertionError();
53 | }
54 | }
55 |
56 | ObjectGraph graph = ObjectGraph.createWith(new TestingLoader(), new TestModule());
57 | try {
58 | graph.validate();
59 | fail();
60 | } catch (RuntimeException expected) {
61 | }
62 | }
63 |
64 | @Test public void validateLazy() {
65 | @Module(library = true)
66 | class TestModule {
67 | @Provides Integer dependOnLazy(Lazy lazyString) {
68 | throw new AssertionError();
69 | }
70 | @Provides String provideLazyValue() {
71 | throw new AssertionError();
72 | }
73 | }
74 |
75 | ObjectGraph graph = ObjectGraph.createWith(new TestingLoader(), new TestModule());
76 | graph.validate();
77 | }
78 |
79 | static class Rock {
80 | @Inject Scissors scissors;
81 | }
82 |
83 | static class Scissors {
84 | @Inject Paper paper;
85 | }
86 |
87 | static class Paper {
88 | @Inject Rock rock;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/core/src/test/java/dagger/internal/FailoverLoaderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Google Inc.
3 | * Copyright (C) 2013 Square Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger.internal;
18 |
19 | import dagger.Module;
20 | import dagger.ObjectGraph;
21 | import dagger.Provides;
22 | import javax.inject.Inject;
23 | import org.junit.Test;
24 | import org.junit.runner.RunWith;
25 | import org.junit.runners.JUnit4;
26 |
27 | import static com.google.common.truth.Truth.assertThat;
28 |
29 | /**
30 | * A test case to deal with fall-back to reflection where the concrete type has been generated
31 | * but the parent has no {@code @Inject} annotation, and so has not been generated.
32 | */
33 | @RunWith(JUnit4.class)
34 | public final class FailoverLoaderTest {
35 |
36 | @Module(injects = Entry$Point.class)
37 | static class TestModule {
38 | @Provides String aString() { return "a"; }
39 | }
40 |
41 | /** A reflective module that will be loaded in place of a generated module for this test. */
42 | static final class TestModule$$ModuleAdapter extends TestingModuleAdapter {
43 | public TestModule$$ModuleAdapter() {
44 | super(TestModule.class, TestModule.class.getAnnotation(Module.class));
45 | }
46 | }
47 |
48 | static class Entry$Point {
49 | @Inject String a;
50 | }
51 |
52 | @Test public void simpleInjectionWithUnGeneratedCode() {
53 | Entry$Point entryPoint = new Entry$Point();
54 | ObjectGraph.create(new TestModule()).inject(entryPoint);
55 | assertThat(entryPoint.a).isEqualTo("a");
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/core/src/test/java/dagger/internal/SingletonBindingTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2013 Square, 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 |
17 | package dagger.internal;
18 |
19 | import org.junit.Before;
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.junit.runners.JUnit4;
23 |
24 | import static com.google.common.truth.Truth.assertThat;
25 |
26 | @RunWith(JUnit4.class)
27 | public final class SingletonBindingTest {
28 | private Binding wrappedBinding;
29 | private Binding singletonBinding;
30 |
31 | @Before public void setUp() {
32 | wrappedBinding = new StringBinding();
33 | singletonBinding = Linker.scope(wrappedBinding);
34 | }
35 |
36 | @Test public void testSingletonBindingIsSingleton() {
37 | assertThat(singletonBinding.isSingleton()).isTrue();
38 | }
39 |
40 | // This next batch of tests validates that SingletonBinding consistently delegates to the wrapped binding for state.
41 | @Test public void testSingletonBindingDelegatesSetLinked() {
42 | singletonBinding.setLinked();
43 | assertThat(wrappedBinding.isLinked()).isTrue();
44 | }
45 |
46 | @Test public void testSingletonBindingDelegatesIsLinked() {
47 | wrappedBinding.setLinked();
48 | assertThat(singletonBinding.isLinked()).isTrue();
49 | }
50 |
51 | @Test public void testSingletonBindingDelegatesSetVisiting() {
52 | singletonBinding.setVisiting(true);
53 | assertThat(wrappedBinding.isVisiting()).isTrue();
54 | }
55 |
56 | @Test public void testSingletonBindingDelegatesIsVisiting() {
57 | wrappedBinding.setVisiting(true);
58 | assertThat(singletonBinding.isVisiting()).isTrue();
59 | }
60 |
61 | @Test public void testSingletonBindingDelegatesSetCycleFree() {
62 | singletonBinding.setCycleFree(true);
63 | assertThat(wrappedBinding.isCycleFree()).isTrue();
64 | }
65 |
66 | @Test public void testSingletonBindingDelegatesIsCycleFree() {
67 | wrappedBinding.setCycleFree(true);
68 | assertThat(singletonBinding.isCycleFree()).isTrue();
69 | }
70 |
71 | private static class StringBinding extends Binding {
72 | private StringBinding() {
73 | super("dummy", "dummy", true, "dummy"); // 3rd arg true => singleton
74 | }
75 |
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/core/src/test/java/dagger/internal/TestingLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, Inc.
3 | * Copyright (C) 2013 Google, Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package dagger.internal;
18 |
19 |
20 | import dagger.internal.loaders.ReflectiveAtInjectBinding;
21 | import dagger.internal.loaders.ReflectiveStaticInjection;
22 |
23 | /**
24 | * A test-only loader that merely uses reflection to test internals.
25 | */
26 | public final class TestingLoader extends Loader {
27 |
28 | @Override public ModuleAdapter getModuleAdapter(Class type) {
29 | ModuleAdapter adapter = TestingModuleAdapter.create(type);
30 | return adapter;
31 | }
32 |
33 | @Override public Binding> getAtInjectBinding(String key, String className, ClassLoader ignored,
34 | boolean mustHaveInjections) {
35 | try {
36 | Class> type = getClass().getClassLoader().loadClass(className);
37 | if (type.isInterface()) {
38 | return null; // Short-circuit since we can't build reflective bindings for interfaces.
39 | }
40 | return ReflectiveAtInjectBinding.create(type, mustHaveInjections);
41 | } catch (ClassNotFoundException e) {
42 | throw new TypeNotPresentException(
43 | String.format("Could not find %s needed for binding %s", className, key), e);
44 | }
45 | }
46 |
47 | @Override public StaticInjection getStaticInjection(Class> injectedClass) {
48 | return ReflectiveStaticInjection.create(injectedClass);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/deploy_website.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Deploys the current Dagger website to the gh-pages branch of the GitHub
4 | # repository. To test the site locally before deploying run `jekyll --server`
5 | # in the website/ directory.
6 |
7 | set -ex
8 |
9 | REPO="git@github.com:square/dagger.git"
10 | DIR=temp-dagger-clone
11 |
12 | # Delete any existing temporary website clone
13 | rm -rf $DIR
14 |
15 | # Clone the current repo into temp folder
16 | git clone $REPO $DIR
17 |
18 | # Move working directory into temp folder
19 | cd $DIR
20 |
21 | # Checkout and track the gh-pages branch
22 | git checkout -t origin/gh-pages
23 |
24 | # Delete everything that isn't versioned (1.x, 2.x)
25 | ls | grep -E -v '^\d+\.x$' | xargs rm -rf
26 |
27 | # Copy website files from real repo
28 | cp -R ../website/* .
29 |
30 | # Stage all files in git and create a commit
31 | git add .
32 | git add -u
33 | git commit -m "Website at $(date)"
34 |
35 | # Push the new files up to GitHub
36 | git push origin gh-pages
37 |
38 | # Delete our temp folder
39 | cd ..
40 | rm -rf $DIR
41 |
--------------------------------------------------------------------------------
/examples/android-activity-graphs/README.md:
--------------------------------------------------------------------------------
1 | Example: Android Activity Graphs
2 | ================================
3 |
4 | Building on top of the simple Android example, this example demonstrates how it is possible to
5 | create child graphs for each activity which extend from the global graph.
6 |
7 | Some of the advantages of the activity scope:
8 |
9 | * Provides the ability to inject objects which require the activity to be constructed.
10 | * Allows for the use of singletons on a per-activity basis. This is a great way to manage a
11 | resource that is shared by a bunch of fragments in an activity.
12 | * Keeps the global object graph clear of things that can be used only by activities.
13 |
14 | While this example only shows the presence of an activity scope, you should be able to see the
15 | potential for other useful scopes that can be used. For example, having a dedicated object graph
16 | for the current user session is a great way to manage data that is tied to the currently logged-in
17 | user.
18 |
19 | _Note: The app does not actually do anything when it is run. It is only to show how you can
20 | structure Dagger within an Android app_
21 |
--------------------------------------------------------------------------------
/examples/android-activity-graphs/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | 4.0.0
19 |
20 |
21 | com.squareup.dagger.example
22 | dagger-example-parent
23 | 1.2.6-SNAPSHOT
24 |
25 |
26 | android-activity-graphs
27 | Examples: Android - Activity Graphs
28 | apk
29 |
30 |
31 |
32 | com.squareup.dagger
33 | dagger
34 | ${project.version}
35 |
36 |
37 | com.squareup.dagger
38 | dagger-compiler
39 | ${project.version}
40 | true
41 |
42 |
43 |
44 | com.google.android
45 | android
46 | provided
47 |
48 |
49 | com.google.android
50 | support-v4
51 |
52 |
53 |
54 |
55 |
56 |
57 | com.simpligility.maven.plugins
58 | android-maven-plugin
59 | true
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/examples/android-activity-graphs/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/examples/android-activity-graphs/src/main/java/com/example/dagger/activitygraphs/ActivityModule.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, 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 | package com.example.dagger.activitygraphs;
17 |
18 | import android.content.Context;
19 | import com.example.dagger.activitygraphs.ui.ActivityTitleController;
20 | import com.example.dagger.activitygraphs.ui.HomeActivity;
21 | import com.example.dagger.activitygraphs.ui.HomeFragment;
22 | import dagger.Module;
23 | import dagger.Provides;
24 | import javax.inject.Singleton;
25 |
26 | /**
27 | * This module represents objects which exist only for the scope of a single activity. We can
28 | * safely create singletons using the activity instance because the entire object graph will only
29 | * ever exist inside of that activity.
30 | */
31 | @Module(
32 | injects = {
33 | HomeActivity.class,
34 | HomeFragment.class
35 | },
36 | addsTo = AndroidModule.class,
37 | library = true
38 | )
39 | public class ActivityModule {
40 | private final DemoBaseActivity activity;
41 |
42 | public ActivityModule(DemoBaseActivity activity) {
43 | this.activity = activity;
44 | }
45 |
46 | /**
47 | * Allow the activity context to be injected but require that it be annotated with
48 | * {@link ForActivity @ForActivity} to explicitly differentiate it from application context.
49 | */
50 | @Provides @Singleton @ForActivity Context provideActivityContext() {
51 | return activity;
52 | }
53 |
54 | @Provides @Singleton ActivityTitleController provideTitleController() {
55 | return new ActivityTitleController(activity);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/examples/android-activity-graphs/src/main/java/com/example/dagger/activitygraphs/AndroidModule.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, 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 | package com.example.dagger.activitygraphs;
17 |
18 | import android.content.Context;
19 | import android.location.LocationManager;
20 | import dagger.Module;
21 | import dagger.Provides;
22 | import javax.inject.Singleton;
23 |
24 | import static android.content.Context.LOCATION_SERVICE;
25 |
26 | /**
27 | * A module for Android-specific dependencies which require a {@link Context} or
28 | * {@link android.app.Application} to create.
29 | */
30 | @Module(library = true)
31 | public class AndroidModule {
32 | private final DemoApplication application;
33 |
34 | public AndroidModule(DemoApplication application) {
35 | this.application = application;
36 | }
37 |
38 | /**
39 | * Allow the application context to be injected but require that it be annotated with
40 | * {@link ForApplication @ForApplication} to explicitly differentiate it from an activity context.
41 | */
42 | @Provides @Singleton @ForApplication Context provideApplicationContext() {
43 | return application;
44 | }
45 |
46 | @Provides @Singleton LocationManager provideLocationManager() {
47 | return (LocationManager) application.getSystemService(LOCATION_SERVICE);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/examples/android-activity-graphs/src/main/java/com/example/dagger/activitygraphs/DemoApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Square, 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 | package com.example.dagger.activitygraphs;
17 |
18 | import android.app.Application;
19 | import dagger.ObjectGraph;
20 | import java.util.Arrays;
21 | import java.util.List;
22 |
23 | public class DemoApplication extends Application {
24 | private ObjectGraph applicationGraph;
25 |
26 | @Override public void onCreate() {
27 | super.onCreate();
28 |
29 | applicationGraph = ObjectGraph.create(getModules().toArray());
30 | }
31 |
32 | /**
33 | * A list of modules to use for the application graph. Subclasses can override this method to
34 | * provide additional modules provided they call {@code super.getModules()}.
35 | */
36 | protected List