View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.cdi.util;
21  
22  import javax.enterprise.context.ContextNotActiveException;
23  import javax.enterprise.context.spi.Context;
24  import javax.enterprise.context.spi.Contextual;
25  import javax.enterprise.context.spi.CreationalContext;
26  import javax.enterprise.inject.spi.BeanManager;
27  import javax.enterprise.inject.spi.PassivationCapable;
28  import java.util.Map;
29  
30  /**
31   * A skeleton containing the most important parts of a custom CDI Context.
32   * An implementing Context needs to implement the missing methods from the
33   * {@link Context} interface and {@link #getContextualStorage(boolean)}.
34   * 
35   * NOTE: Taken from Apache DeltaSpike
36   */
37  public abstract class AbstractContext implements Context
38  {
39      /**
40       * Whether the Context is for a passivating scope.
41       */
42      private final boolean passivatingScope;
43  
44      protected AbstractContext(BeanManager beanManager)
45      {
46          passivatingScope = beanManager.isPassivatingScope(getScope());
47      }
48  
49      /**
50       * An implementation has to return the underlying storage which
51       * contains the items held in the Context.
52       * @param createIfNotExist whether a ContextualStorage shall get created if it doesn't yet exist.
53       * @return the underlying storage
54       */
55      protected abstract ContextualStorage getContextualStorage(boolean createIfNotExist);
56  
57      /**
58       * @return whether the served scope is a passivating scope
59       */
60      public boolean isPassivatingScope()
61      {
62          return passivatingScope;
63      }
64  
65      @Override
66      public <T> T get(Contextual<T> bean)
67      {
68          checkActive();
69  
70          ContextualStorage storage = getContextualStorage(false);
71          if (storage == null)
72          {
73              return null;
74          }
75  
76          Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
77          ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
78          if (contextualInstanceInfo == null)
79          {
80              return null;
81          }
82  
83          return (T) contextualInstanceInfo.getContextualInstance();
84      }
85  
86      @Override
87      public <T> T get(Contextual<T> bean, CreationalContext<T> creationalContext)
88      {
89          checkActive();
90  
91          if (passivatingScope)
92          {
93              if (!(bean instanceof PassivationCapable))
94              {
95                  throw new IllegalStateException(bean.toString() +
96                          " doesn't implement " + PassivationCapable.class.getName());
97              }
98          }
99  
100         ContextualStorage storage = getContextualStorage(true);
101 
102         Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
103         ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
104 
105         if (contextualInstanceInfo != null)
106         {
107             @SuppressWarnings("unchecked")
108             final T instance =  (T) contextualInstanceInfo.getContextualInstance();
109 
110             if (instance != null)
111             {
112                 return instance;
113             }
114         }
115 
116         return storage.createContextualInstance(bean, creationalContext);
117     }
118 
119     /**
120      * Destroy the Contextual Instance of the given Bean.
121      * @param bean dictates which bean shall get cleaned up
122      * @return <code>true</code> if the bean was destroyed, <code>false</code> if there was no such bean.
123      */
124     public boolean destroy(Contextual bean)
125     {
126         ContextualStorage storage = getContextualStorage(false);
127         if (storage == null)
128         {
129             return false;
130         }
131         ContextualInstanceInfo<?> contextualInstanceInfo = storage.getStorage().get(storage.getBeanKey(bean));
132 
133         if (contextualInstanceInfo == null)
134         {
135             return false;
136         }
137 
138         bean.destroy(contextualInstanceInfo.getContextualInstance(), contextualInstanceInfo.getCreationalContext());
139 
140         return true;
141     }
142 
143     /**
144      * destroys all the Contextual Instances in the Storage returned by
145      * {@link #getContextualStorage(boolean)}.
146      */
147     public void destroyAllActive()
148     {
149         ContextualStorage storage = getContextualStorage(false);
150         if (storage == null)
151         {
152             return;
153         }
154 
155         destroyAllActive(storage);
156     }
157 
158     /**
159      * Destroys all the Contextual Instances in the specified ContextualStorage.
160      * This is a static method to allow various holder objects to cleanup
161      * properly in &#064;PreDestroy.
162      */
163     public static void destroyAllActive(ContextualStorage storage)
164     {
165         Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
166         for (Map.Entry<Object, ContextualInstanceInfo<?>> entry : contextMap.entrySet())
167         {
168             Contextual bean = storage.getBean(entry.getKey());
169 
170             ContextualInstanceInfo<?> contextualInstanceInfo = entry.getValue();
171             bean.destroy(contextualInstanceInfo.getContextualInstance(), contextualInstanceInfo.getCreationalContext());
172         }
173     }
174 
175     /**
176      * Make sure that the Context is really active.
177      * @throws ContextNotActiveException if there is no active
178      *         Context for the current Thread.
179      */
180     protected void checkActive()
181     {
182         if (!isActive())
183         {
184             throw new ContextNotActiveException("CDI context with scope annotation @"
185                 + getScope().getName() + " is not active with respect to the current thread");
186         }
187     }
188 
189 }