blob: ff3d06888f68c3b2969fbf9da3665ce0e190ccf8 [file] [log] [blame]
crazybobleeabc4dd02007-02-01 01:44:36 +00001/**
2 * Copyright (C) 2006 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 */
crazyboblee63b592b2007-01-25 02:45:24 +000016
17package com.google.inject;
18
crazybobleeb1f2e682007-02-15 05:14:32 +000019import java.lang.annotation.Annotation;
crazyboblee278ee4d2007-02-15 19:23:13 +000020import java.util.Map;
crazybobleef33d23e2007-02-12 04:17:48 +000021
crazyboblee63b592b2007-01-25 02:45:24 +000022/**
crazybobleee5fbbb02007-02-05 07:00:27 +000023 * Built in scope implementations.
crazyboblee63b592b2007-01-25 02:45:24 +000024 *
25 * @author crazybob@google.com (Bob Lee)
26 */
crazyboblee68d2f4b2007-02-07 18:47:24 +000027public class Scopes {
28
crazybobleef33d23e2007-02-12 04:17:48 +000029 private Scopes() {}
crazyboblee63b592b2007-01-25 02:45:24 +000030
31 /**
crazyboblee68d2f4b2007-02-07 18:47:24 +000032 * The default scope, one instance per injection.
33 */
34 public static final Scope DEFAULT = new Scope() {
crazybobleee5fbbb02007-02-05 07:00:27 +000035 public <T> Factory<T> scope(Key<T> key, Factory<T> creator) {
36 return creator;
37 }
crazybobleef33d23e2007-02-12 04:17:48 +000038
39 public String toString() {
crazybobleeb1f2e682007-02-15 05:14:32 +000040 return "Scopes.DEFAULT";
crazybobleef33d23e2007-02-12 04:17:48 +000041 }
crazyboblee68d2f4b2007-02-07 18:47:24 +000042 };
43
44 /**
crazyboblee278ee4d2007-02-15 19:23:13 +000045 * One instance per container. Also see {@code @}{@link ContainerScoped}.
crazyboblee63b592b2007-01-25 02:45:24 +000046 */
crazyboblee68d2f4b2007-02-07 18:47:24 +000047 public static final Scope CONTAINER = new Scope() {
crazybobleee5fbbb02007-02-05 07:00:27 +000048 public <T> Factory<T> scope(Key<T> key, final Factory<T> creator) {
49 return new Factory<T>() {
50
51 private volatile T instance;
52
crazybobleef33d23e2007-02-12 04:17:48 +000053 // DCL on a volatile is safe as of Java 5, which we obviously require.
kevinb9n6a565c72007-02-11 01:58:33 +000054 @SuppressWarnings("DoubleCheckedLocking")
crazybobleee5fbbb02007-02-05 07:00:27 +000055 public T get() {
crazybobleee5fbbb02007-02-05 07:00:27 +000056 if (instance == null) {
kevinb9na99dca72007-02-11 04:48:57 +000057 /*
58 * Use a pretty coarse lock. We don't want to run into deadlocks
59 * when two threads try to load circularly-dependent objects.
60 * Maybe one of these days we will identify independent graphs of
61 * objects and offer to load them in parallel.
62 */
crazybobleee5fbbb02007-02-05 07:00:27 +000063 synchronized (Container.class) {
64 if (instance == null) {
65 instance = creator.get();
66 }
67 }
68 }
69 return instance;
70 }
71
72 public String toString() {
73 return creator.toString();
74 }
75 };
76 }
crazybobleef33d23e2007-02-12 04:17:48 +000077
78 public String toString() {
crazybobleeb1f2e682007-02-15 05:14:32 +000079 return "Scopes.CONTAINER";
crazybobleef33d23e2007-02-12 04:17:48 +000080 }
crazyboblee68d2f4b2007-02-07 18:47:24 +000081 };
crazybobleef33d23e2007-02-12 04:17:48 +000082
83 /**
84 * Gets the scope for a type based on its annotations. Returns {@code null}
85 * if none specified.
86 *
87 * @param implementation type
88 * @param scopes map of scope names to scopes
89 * @param errorHandler handles errors
90 */
91 static Scope getScopeForType(Class<?> implementation,
crazybobleeb1f2e682007-02-15 05:14:32 +000092 Map<Class<? extends Annotation>, Scope> scopes,
crazybobleef33d23e2007-02-12 04:17:48 +000093 ErrorHandler errorHandler) {
crazybobleeb1f2e682007-02-15 05:14:32 +000094 Scope found = null;
95 for (Annotation annotation : implementation.getAnnotations()) {
96 Scope scope = scopes.get(annotation.annotationType());
97 if (scope != null) {
98 if (found != null) {
99 errorHandler.handle(ErrorMessages.DUPLICATE_SCOPE_ANNOTATIONS,
100 implementation, found, scope);
101 } else {
102 found = scope;
103 }
104 }
crazybobleef33d23e2007-02-12 04:17:48 +0000105 }
crazybobleeb1f2e682007-02-15 05:14:32 +0000106 return found;
crazybobleef33d23e2007-02-12 04:17:48 +0000107 }
108
109 /**
110 * Scopes an internal factory.
111 */
112 static <T> InternalFactory<? extends T> scope(Key<T> key,
113 ContainerImpl container, InternalFactory<? extends T> creator,
114 Scope scope) {
115 // Default scope does nothing.
116 if (scope == null || scope == DEFAULT) {
117 return creator;
118 }
crazybobleef33d23e2007-02-12 04:17:48 +0000119 Factory<T> scoped = scope.scope(key,
120 new FactoryToInternalFactoryAdapter<T>(container, creator));
121 return new InternalFactoryToFactoryAdapter<T>(scoped);
122 }
kevinb9na99dca72007-02-11 04:48:57 +0000123}