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.context.MgnlContext;
37 import info.magnolia.context.WebContext;
38
39 import javax.servlet.http.HttpServletRequest;
40 import javax.servlet.http.HttpSession;
41
42 import com.google.inject.Key;
43 import com.google.inject.OutOfScopeException;
44 import com.google.inject.Provider;
45 import com.google.inject.Scope;
46 import com.google.inject.Scopes;
47 import com.mycila.inject.annotation.Jsr250Singleton;
48
49
50
51
52
53
54 public class MagnoliaScopes {
55
56 private MagnoliaScopes() {
57 }
58
59 public static final Scope LAZY_SINGLETON = new LazySingletonScope();
60
61
62
63
64 public static final Scope LOCAL = new LocalScope();
65
66
67
68
69 public static final Scope SESSION = new SessionScope();
70
71
72
73
74
75
76
77 @Jsr250Singleton
78 public static class LazySingletonScope implements Scope {
79
80 @Override
81 public <T> Provider<T> scope(Key<T> key, Provider<T> creator) {
82 return Scopes.SINGLETON.scope(key, creator);
83 }
84
85 @Override
86 public String toString() {
87 return "MagnoliaScopes.LAZY_SINGLETON";
88 }
89 }
90
91
92
93
94 enum NullObject {
95 INSTANCE
96 }
97
98
99
100
101
102
103
104 public static class LocalScope implements Scope {
105
106 @Override
107 public <T> Provider<T> scope(Key<T> key, final Provider<T> creator) {
108 final String name = key.toString();
109 return new Provider<T>() {
110 @Override
111 public T get() {
112
113 HttpServletRequest request = getRequest();
114
115 if (request == null) {
116 return null;
117 }
118
119 synchronized (request) {
120 Object obj = request.getAttribute(name);
121 if (NullObject.INSTANCE == obj) {
122 return null;
123 }
124 @SuppressWarnings("unchecked")
125 T t = (T) obj;
126 if (t == null) {
127 t = creator.get();
128 request.setAttribute(name, (t != null) ? t : NullObject.INSTANCE);
129 }
130 return t;
131 }
132 }
133
134 @Override
135 public String toString() {
136 return String.format("%s[%s]", creator, LOCAL);
137 }
138 };
139 }
140
141 @Override
142 public String toString() {
143 return "MagnoliaScopes.LOCAL";
144 }
145 }
146
147
148
149
150
151
152
153 public static class SessionScope implements Scope {
154
155 @Override
156 public <T> Provider<T> scope(Key<T> key, final Provider<T> creator) {
157 final String name = key.toString();
158 return new Provider<T>() {
159 @Override
160 public T get() {
161
162 HttpSession session = getSession();
163
164 synchronized (session) {
165 Object obj = session.getAttribute(name);
166 if (NullObject.INSTANCE == obj) {
167 return null;
168 }
169 @SuppressWarnings("unchecked")
170 T t = (T) obj;
171 if (t == null) {
172 t = creator.get();
173 session.setAttribute(name, (t != null) ? t : NullObject.INSTANCE);
174 }
175 return t;
176 }
177 }
178
179 @Override
180 public String toString() {
181 return String.format("%s[%s]", creator, SESSION);
182 }
183 };
184 }
185
186 @Override
187 public String toString() {
188 return "MagnoliaScopes.SESSION";
189 }
190 }
191
192 private static HttpServletRequest getRequest() {
193 WebContext webContext;
194 try {
195 webContext = MgnlContext.getWebContextOrNull();
196
197 if (webContext == null) {
198 return null;
199 }
200 } catch (IllegalStateException e) {
201 throw new OutOfScopeException("Cannot access scoped object." +
202 " MgnlContext does not have a WebContext set, this is most likely" +
203 " because we are not currently processing a HTTP request.", e);
204 }
205 HttpServletRequest request = webContext.getRequest();
206 if (request == null) {
207 throw new OutOfScopeException("Cannot access scoped object." +
208 " MgnlContext does not have a HttpServletRequest set, this is most likely" +
209 " because we are not currently processing a HTTP request.");
210 }
211 return request;
212 }
213
214 private static HttpSession getSession() {
215 try {
216 return getRequest().getSession();
217 } catch (IllegalStateException e) {
218 throw new OutOfScopeException("Cannot access scoped object." +
219 " A session is not available and a new one could not be created," +
220 " likely because the response has already been committed.", e);
221 }
222 }
223 }