KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > directwebremoting > guice > AbstractContextScope


1 /*
2  * Copyright 2007 Tim Peierls
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 org.directwebremoting.guice;
17
18 import com.google.inject.Key;
19 import com.google.inject.Provider;
20 import com.google.inject.Scope;
21 import com.google.inject.util.ToStringBuilder;
22
23 import java.util.Collection JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.List JavaDoc;
26 import static java.util.Collections.synchronizedList JavaDoc;
27 import static java.util.Collections.unmodifiableList JavaDoc;
28
29 import java.util.concurrent.Callable JavaDoc;
30 import java.util.concurrent.ConcurrentHashMap JavaDoc;
31 import java.util.concurrent.ConcurrentMap JavaDoc;
32 import java.util.concurrent.ExecutionException JavaDoc;
33 import java.util.concurrent.Future JavaDoc;
34 import java.util.concurrent.FutureTask JavaDoc;
35
36 import org.directwebremoting.util.Logger;
37 import static org.directwebremoting.guice.AbstractContextScope.State.*;
38
39 /**
40  * Partial implementation of {@link ContextScope}. Concrete implementations
41  * must pass the context identifier type to the super constructor and define
42  * {@code get()} to return the current context identifier (and to return null
43  * or throw an exception if there is no current context). They must also implement
44  * the {@link ContextRegistry} interface.
45  * @author Tim Peierls [tim at peierls dot net]
46  */

47 public abstract class AbstractContextScope<C, R>
48     implements ContextScope<C>, ContextRegistry<C, R>
49 {
50     protected AbstractContextScope(Class JavaDoc<C> type, String JavaDoc scopeName)
51     {
52         this.type = type;
53         this.scopeName = scopeName;
54     }
55     
56     public String JavaDoc toString()
57     {
58         return scopeName;
59     }
60     
61     public List JavaDoc<Key<?>> getKeysInScope()
62     {
63         synchronized (scopedKeys)
64         {
65             return new ArrayList JavaDoc<Key<?>>(scopedKeys);
66         }
67     }
68     
69     public <T> Provider<T> scope(final Key<T> key, final Provider<T> creator)
70     {
71         if (log.isDebugEnabled())
72         {
73             log.debug(String.format(
74                 "scope %s: adding key %s with creator %s",
75                 scopeName, key, creator
76             ));
77         }
78         
79         scopedKeys.add(key);
80         final String JavaDoc name = key.toString();
81         return new Provider<T>()
82         {
83             public T get()
84             {
85                 if (log.isDebugEnabled())
86                 {
87                     log.debug(String.format(
88                         "scope %s: getting key %s with creator %s",
89                         scopeName, key, creator
90                     ));
91                 }
92         
93                 C context = getContext(key);
94                 R registry = registryFor(context);
95                 InstanceProvider<T> future =
96                     AbstractContextScope.this.get(registry, key, name);
97                 if (future == null)
98                 {
99                     InstanceProvider<T> futureTask = new FutureTaskProvider<T>(creator);
100                     future = putIfAbsent(registry, key, name, futureTask);
101                     if (future == null)
102                     {
103                         future = futureTask;
104                         futureTask.run();
105                         if (Thread.currentThread().isInterrupted())
106                         {
107                             remove(registry, key, name, futureTask);
108                         }
109                     }
110                 }
111                 return future.get();
112             }
113
114             public String JavaDoc toString()
115             {
116                 return new ToStringBuilder(this.getClass())
117                     .add("scopeName", scopeName)
118                     .add("type", type)
119                     .add("key", key)
120                     .add("creator", creator)
121                     .toString();
122             }
123         };
124     }
125
126     public abstract C get();
127
128
129     public Class JavaDoc<C> type()
130     {
131         return type;
132     }
133     
134     public Collection JavaDoc<C> getOpenContexts()
135     {
136         Collection JavaDoc<C> openContexts = new ArrayList JavaDoc<C>();
137         for (C context : contexts.keySet())
138         {
139             if (contexts.get(context) == OPEN)
140             {
141                 openContexts.add(context);
142             }
143         }
144         return openContexts;
145     }
146     
147     public void close(C context, ContextCloseHandler<?>... closeHandlers)
148     {
149         if (!contexts.replace(context, OPEN, CLOSED))
150         {
151             // Context hadn't been opened or was already closed.
152
return;
153         }
154         
155         for (InstanceProvider<?> provider : registeredProviders(registryFor(context)))
156         {
157             Object JavaDoc value = null;
158             try
159             {
160                 value = provider.get();
161             }
162             catch (RuntimeException JavaDoc e)
163             {
164                 // Ignore runtime exceptions: they were thrown when
165
// attempting creation and mean that no object was
166
// created.
167
}
168             
169             if (value == null)
170             {
171                 // No instance was created by this provider, so we ignore.
172
continue;
173             }
174             
175             for (ContextCloseHandler<?> closeHandler : closeHandlers)
176             {
177                 handleClose(closeHandler, value);
178             }
179         }
180     }
181     
182     public void closeAll(ContextCloseHandler<?>... closeHandlers)
183     {
184         for (C context : getOpenContexts())
185         {
186             close(context, closeHandlers);
187         }
188     }
189     
190     private <T> void handleClose(ContextCloseHandler<T> closeHandler, Object JavaDoc value)
191     {
192         Class JavaDoc<T> type = closeHandler.type();
193         if (type.isInstance(value))
194         {
195             try
196             {
197                 closeHandler.close(type.cast(value));
198             }
199             catch (Exception JavaDoc e)
200             {
201                 // Ignore exceptions when closing,
202
// the closeHandler should have taken
203
// appropriate action before rethrowing.
204
}
205         }
206     }
207     
208     private C getContext(Key<?> key)
209     {
210         C context = null;
211         RuntimeException JavaDoc caught = null;
212         try
213         {
214             context = get();
215             if (contexts.putIfAbsent(context, OPEN) == CLOSED)
216             {
217                 // Context is closed.
218
context = null;
219             }
220         }
221         catch (RuntimeException JavaDoc ex)
222         {
223             caught = ex;
224         }
225         if (context == null)
226         {
227             throw new OutOfScopeException(this, key, caught);
228         }
229         
230         return context;
231     }
232     
233     private Collection JavaDoc<InstanceProvider<?>> registeredProviders(R registry)
234     {
235         List JavaDoc<InstanceProvider<?>> providers = new ArrayList JavaDoc<InstanceProvider<?>>();
236         for (Key<?> key : getKeysInScope())
237         {
238             InstanceProvider<?> provider = get(registry, key, key.toString());
239             if (provider != null)
240             {
241                 providers.add(provider);
242             }
243         }
244         return providers;
245     }
246     
247     enum State
248     {
249         OPEN,
250         CLOSED
251     }
252     
253     private final Class JavaDoc<C> type;
254     
255     private final String JavaDoc scopeName;
256     
257     /* @GuardedBy("self") */
258     private final List JavaDoc<Key<?>> scopedKeys = synchronizedList(new ArrayList JavaDoc<Key<?>>());
259     
260     private final ConcurrentMap JavaDoc<C, State> contexts = new ConcurrentHashMap JavaDoc<C, State>();
261
262     /**
263      * The log stream
264      */

265     private static final Logger log = Logger.getLogger(AbstractContextScope.class);
266 }
267
Popular Tags