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.view;
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 javax.enterprise.inject.spi.Bean;
31  import javax.faces.context.FacesContext;
32  import org.apache.myfaces.cdi.util.CDIUtils;
33  import org.apache.myfaces.cdi.util.ContextualInstanceInfo;
34  
35  /**
36   * This Storage holds all information needed for storing
37   * View Scope instances in a context.
38   * 
39   * This scope requires passivation and is not concurrent.
40   */
41  public class ViewScopeContextualStorage implements Serializable
42  {
43      private static final long serialVersionUID = 1L;
44  
45      private final Map<Object, ContextualInstanceInfo<?>> contextualInstances;
46      
47      private final Map<String, Object> nameBeanKeyMap;
48      
49      private transient BeanManager beanManager;
50      
51      private transient volatile boolean deactivated;
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 ViewScopeContextualStorage(BeanManager beanManager)
59      {
60          this.beanManager = beanManager;
61          contextualInstances = new HashMap<Object, ContextualInstanceInfo<?>>();
62          nameBeanKeyMap = new HashMap<String, Object>();
63          deactivated = false;
64      }
65  
66      /**
67       * @return the underlying storage map.
68       */
69      public Map<Object, ContextualInstanceInfo<?>> getStorage()
70      {
71          return contextualInstances;
72      }
73      
74      public Map<String, Object> getNameBeanKeyMap()
75      {
76          return nameBeanKeyMap;
77      }
78  
79      /**
80       *
81       * @param bean
82       * @param creationalContext
83       * @param <T>
84       * @return
85       */
86      public <T> T createContextualInstance(Contextual<T> bean, CreationalContext<T> creationalContext)
87      {
88          Object beanKey = getBeanKey(bean);
89  
90          // simply create the contextual instance
91          ContextualInstanceInfo<T> instanceInfo = new ContextualInstanceInfo<T>();
92          instanceInfo.setCreationalContext(creationalContext);
93          instanceInfo.setContextualInstance(bean.create(creationalContext));
94  
95          contextualInstances.put(beanKey, instanceInfo);
96          if(bean instanceof Bean)
97          {
98              String name = ((Bean<T>) bean).getName();
99              if (name != null)
100             {
101                 nameBeanKeyMap.put(name, beanKey);
102             }
103         }
104 
105         return instanceInfo.getContextualInstance();
106     }
107 
108     /**
109      * If the context is a passivating scope then we return
110      * the passivationId of the Bean. Otherwise we use
111      * the Bean directly.
112      * @return the key to use in the context map
113      */
114     public <T> Object getBeanKey(Contextual<T> bean)
115     {
116         return ((PassivationCapable) bean).getId();
117     }
118 
119     /**
120      * Restores the Bean from its beanKey.
121      * @see #getBeanKey(javax.enterprise.context.spi.Contextual)
122      */
123     public Contextual<?> getBean(FacesContext context, Object beanKey)
124     {
125         if (beanManager == null)
126         {
127             beanManager = CDIUtils.getBeanManager(context.getExternalContext());
128         }
129         return beanManager.getPassivationCapableBean((String) beanKey);
130     }
131     
132     public boolean isActive()
133     {
134         return !deactivated;
135     }
136     
137     public void deactivate()
138     {
139         deactivated = true;
140     }
141 }