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