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  
23  import javax.enterprise.context.spi.Contextual;
24  import javax.enterprise.context.spi.CreationalContext;
25  import javax.enterprise.inject.spi.BeanManager;
26  import javax.enterprise.inject.spi.PassivationCapable;
27  import java.io.Serializable;
28  import java.util.HashMap;
29  import java.util.Map;
30  import java.util.concurrent.ConcurrentHashMap;
31  import java.util.concurrent.ConcurrentMap;
32  
33  /**
34   * This Storage holds all information needed for storing
35   * Contextual Instances in a Context.
36   *
37   * It also addresses Serialisation in case of passivating scopes.
38   * 
39   * NOTE: Taken from Apache DeltaSpike
40   */
41  public class ContextualStorage implements Serializable
42  {
43      private static final long serialVersionUID = 1L;
44  
45      private final Map<Object, ContextualInstanceInfo<?>> contextualInstances;
46  
47      private final BeanManager beanManager;
48  
49      private final boolean concurrent;
50  
51      private final boolean passivationCapable;
52  
53      /**
54       * @param beanManager is needed for serialisation
55       * @param concurrent whether the ContextualStorage might get accessed concurrently by different threads
56       * @param passivationCapable whether the storage is for passivation capable Scopes
57       */
58      public ContextualStorage(BeanManager beanManager, boolean concurrent, boolean passivationCapable)
59      {
60          this.beanManager = beanManager;
61          this.concurrent = concurrent;
62          this.passivationCapable = passivationCapable;
63          if (concurrent)
64          {
65              contextualInstances = new ConcurrentHashMap<Object, ContextualInstanceInfo<?>>();
66          }
67          else
68          {
69              contextualInstances = new HashMap<Object, ContextualInstanceInfo<?>>();
70          }
71      }
72  
73      /**
74       * @return the underlying storage map.
75       */
76      public Map<Object, ContextualInstanceInfo<?>> getStorage()
77      {
78          return contextualInstances;
79      }
80  
81      /**
82       * @return whether the ContextualStorage might get accessed concurrently by different threads.
83       */
84      public boolean isConcurrent()
85      {
86          return concurrent;
87      }
88  
89      /**
90       *
91       * @param bean
92       * @param creationalContext
93       * @param <T>
94       * @return
95       */
96      public <T> T createContextualInstance(Contextual<T> bean, CreationalContext<T> creationalContext)
97      {
98          Object beanKey = getBeanKey(bean);
99          if (isConcurrent())
100         {
101             // locked approach
102             ContextualInstanceInfo<T> instanceInfo = new ContextualInstanceInfo<T>();
103 
104             ConcurrentMap<Object, ContextualInstanceInfo<?>> concurrentMap
105                 = (ConcurrentHashMap<Object, ContextualInstanceInfo<?>>) contextualInstances;
106 
107             ContextualInstanceInfo<T> oldInstanceInfo
108                 = (ContextualInstanceInfo<T>) concurrentMap.putIfAbsent(beanKey, instanceInfo);
109 
110             if (oldInstanceInfo != null)
111             {
112                 instanceInfo = oldInstanceInfo;
113             }
114             synchronized (instanceInfo)
115             {
116                 T instance = instanceInfo.getContextualInstance();
117                 if (instance == null)
118                 {
119                     instance = bean.create(creationalContext);
120                     instanceInfo.setContextualInstance(instance);
121                     instanceInfo.setCreationalContext(creationalContext);
122                 }
123 
124                 return instance;
125             }
126 
127         }
128         else
129         {
130             // simply create the contextual instance
131             ContextualInstanceInfo<T> instanceInfo = new ContextualInstanceInfo<T>();
132             instanceInfo.setCreationalContext(creationalContext);
133             instanceInfo.setContextualInstance(bean.create(creationalContext));
134 
135             contextualInstances.put(beanKey, instanceInfo);
136 
137             return instanceInfo.getContextualInstance();
138         }
139     }
140 
141     /**
142      * If the context is a passivating scope then we return
143      * the passivationId of the Bean. Otherwise we use
144      * the Bean directly.
145      * @return the key to use in the context map
146      */
147     public <T> Object getBeanKey(Contextual<T> bean)
148     {
149         if (passivationCapable)
150         {
151             // if the
152             return ((PassivationCapable) bean).getId();
153         }
154 
155         return bean;
156     }
157 
158     /**
159      * Restores the Bean from its beanKey.
160      * @see #getBeanKey(javax.enterprise.context.spi.Contextual)
161      */
162     public Contextual<?> getBean(Object beanKey)
163     {
164         if (passivationCapable)
165         {
166             return beanManager.getPassivationCapableBean((String) beanKey);
167         }
168         else
169         {
170             return (Contextual<?>) beanKey;
171         }
172     }
173 }