You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by gp...@apache.org on 2010/09/25 01:01:38 UTC

svn commit: r1001103 - in /myfaces/extensions/cdi/trunk: core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/utils/ examples/jsf-examples/hello_myfa...

Author: gpetracek
Date: Fri Sep 24 23:01:37 2010
New Revision: 1001103

URL: http://svn.apache.org/viewvc?rev=1001103&view=rev
Log:
EXTCDI-1, EXTCDI-2 and EXTCDI-3 support for close-conversation with qualifiers

Modified:
    myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ConversationBeanEntry.java
    myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/utils/CodiUtils.java
    myfaces/extensions/cdi/trunk/examples/jsf-examples/hello_myfaces-codi_jsf12/src/main/java/org/apache/myfaces/examples/codi/jsf12/conversation/grouped/ConversationDemoBean1.java
    myfaces/extensions/cdi/trunk/examples/jsf-examples/hello_myfaces-codi_jsf12/src/main/webapp/helloMyFacesCodi.jsp
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/api/src/main/java/org/apache/myfaces/extensions/cdi/jsf/api/listener/phase/PhaseId.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/BeanStorage.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultConversation.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultConversationKey.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultWindowContextManager.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/JsfWindowContext.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ExceptionUtils.java

Modified: myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ConversationBeanEntry.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ConversationBeanEntry.java?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ConversationBeanEntry.java (original)
+++ myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ConversationBeanEntry.java Fri Sep 24 23:01:37 2010
@@ -133,4 +133,10 @@ class ConversationBeanEntry<T> implement
     {
         return BeanManagerProvider.getInstance().getBeanManager();
     }
+
+    @Override
+    public String toString()
+    {
+        return this.bean.toString();
+    }
 }

Modified: myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/utils/CodiUtils.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/utils/CodiUtils.java?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/utils/CodiUtils.java (original)
+++ myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/utils/CodiUtils.java Fri Sep 24 23:01:37 2010
@@ -29,11 +29,16 @@ import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.InjectionTarget;
 import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.util.Nonbinding;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Properties;
 import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
 
 /**
  * This is a collection of a few useful static helper functions.
@@ -220,4 +225,97 @@ public class CodiUtils
         injectionTarget.inject(instance, creationalContext);
         return instance;
     }
+
+    /*
+     * source cod from OWB
+     */
+    //method from OWB AnnotationUtil#hasAnnotationMember - TODO test & refactor it
+    public static boolean isQualifierEqual(Annotation sourceAnnotation, Annotation targetAnnotation)
+    {
+        Class<? extends Annotation> sourceAnnotationType = sourceAnnotation.annotationType();
+
+        if (!sourceAnnotation.annotationType().equals(targetAnnotation.annotationType()))
+        {
+            return false;
+        }
+
+        Method[] methods = sourceAnnotationType.getDeclaredMethods();
+
+        List<String> list = new ArrayList<String>();
+
+        for (Method method : methods)
+        {
+            Annotation[] annots = method.getDeclaredAnnotations();
+
+            if (annots.length > 0)
+            {
+                for (Annotation annot : annots)
+                {
+                    if (!annot.annotationType().equals(Nonbinding.class))
+                    {
+                        list.add(method.getName());
+                    }
+                }
+            }
+            else
+            {
+                list.add(method.getName());
+            }
+        }
+
+        return checkEquality(sourceAnnotation.toString(), targetAnnotation.toString(), list);
+    }
+    
+    //method from OWB AnnotationUtil#hasAnnotationMember - TODO test & refactor it
+    private static boolean checkEquality(String src, String member, List<String> arguments)
+    {
+        if ((checkEquBuffer(src, arguments).toString().trim()
+                .equals(checkEquBuffer(member, arguments).toString().trim())))
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    //method from OWB AnnotationUtil#hasAnnotationMember - TODO test & refactor it
+    private static StringBuffer checkEquBuffer(String src, List<String> arguments)
+    {
+        int index = src.indexOf('(');
+
+        String sbstr = src.substring(index + 1, src.length() - 1);
+
+        StringBuffer srcBuf = new StringBuffer();
+
+        StringTokenizer tok = new StringTokenizer(sbstr, ",");
+        while (tok.hasMoreTokens())
+        {
+            String token = tok.nextToken();
+
+            StringTokenizer tok2 = new StringTokenizer(token, "=");
+            while (tok2.hasMoreElements())
+            {
+                String tt = tok2.nextToken();
+                if (arguments.contains(tt.trim()))
+                {
+                    srcBuf.append(tt);
+                    srcBuf.append("=");
+
+                    if (tok2.hasMoreElements())
+                    {
+                        String str = tok2.nextToken();
+                        if(str.charAt(0) == '"' && str.charAt(str.length() -1) == '"')
+                        {
+                            str = str.substring(1,str.length()-1);
+                        }
+
+                        srcBuf.append(str);
+                    }
+                }
+            }
+
+        }
+
+        return srcBuf;
+    }
 }

Modified: myfaces/extensions/cdi/trunk/examples/jsf-examples/hello_myfaces-codi_jsf12/src/main/java/org/apache/myfaces/examples/codi/jsf12/conversation/grouped/ConversationDemoBean1.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/examples/jsf-examples/hello_myfaces-codi_jsf12/src/main/java/org/apache/myfaces/examples/codi/jsf12/conversation/grouped/ConversationDemoBean1.java?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/examples/jsf-examples/hello_myfaces-codi_jsf12/src/main/java/org/apache/myfaces/examples/codi/jsf12/conversation/grouped/ConversationDemoBean1.java (original)
+++ myfaces/extensions/cdi/trunk/examples/jsf-examples/hello_myfaces-codi_jsf12/src/main/java/org/apache/myfaces/examples/codi/jsf12/conversation/grouped/ConversationDemoBean1.java Fri Sep 24 23:01:37 2010
@@ -22,7 +22,9 @@ import org.apache.myfaces.extensions.cdi
 import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.ConversationGroup;
 import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.WindowContext;
 import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.Conversation;
+import org.apache.myfaces.extensions.cdi.core.api.tools.DefaultAnnotation;
 import org.apache.myfaces.examples.codi.jsf12.view.DemoPages;
+import org.apache.myfaces.examples.codi.jsf12.conversation.grouped.qualifier.Qualifier3;
 
 import javax.inject.Named;
 import javax.inject.Inject;
@@ -65,6 +67,12 @@ public class ConversationDemoBean1 imple
         return null;
     }
 
+    public String endGroup1WithQualifiers()
+    {
+        this.windowContext.closeConversation(ConversationGroup1.class, DefaultAnnotation.of(Qualifier3.class));
+        return null;
+    }
+
     public String endConversation()
     {
         //this.conversation.end();

Modified: myfaces/extensions/cdi/trunk/examples/jsf-examples/hello_myfaces-codi_jsf12/src/main/webapp/helloMyFacesCodi.jsp
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/examples/jsf-examples/hello_myfaces-codi_jsf12/src/main/webapp/helloMyFacesCodi.jsp?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/examples/jsf-examples/hello_myfaces-codi_jsf12/src/main/webapp/helloMyFacesCodi.jsp (original)
+++ myfaces/extensions/cdi/trunk/examples/jsf-examples/hello_myfaces-codi_jsf12/src/main/webapp/helloMyFacesCodi.jsp Fri Sep 24 23:01:37 2010
@@ -51,6 +51,7 @@
                 <h:panelGrid>
                     <h:commandLink value="next" action="#{conversationDemoBean1.next}"/>
                     <h:commandLink value="end conversation group 1" action="#{conversationDemoBean1.endGroup1}"/>
+                    <h:commandLink value="end conversation group 1 with qualifier" action="#{conversationDemoBean1.endGroup1WithQualifiers}"/>
                     <h:commandLink value="end conversation of bean" action="#{conversationDemoBean1.endConversation}"/>
                 </h:panelGrid>
             </h:form>

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/api/src/main/java/org/apache/myfaces/extensions/cdi/jsf/api/listener/phase/PhaseId.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/api/src/main/java/org/apache/myfaces/extensions/cdi/jsf/api/listener/phase/PhaseId.java?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/api/src/main/java/org/apache/myfaces/extensions/cdi/jsf/api/listener/phase/PhaseId.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/api/src/main/java/org/apache/myfaces/extensions/cdi/jsf/api/listener/phase/PhaseId.java Fri Sep 24 23:01:37 2010
@@ -19,6 +19,8 @@
 package org.apache.myfaces.extensions.cdi.jsf.api.listener.phase;
 
 /**
+ * It isn't possible to use the original implementation of JSF in combination with annotations
+ * 
  * @author Gerhard Petracek
  */
 public enum PhaseId

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/BeanStorage.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/BeanStorage.java?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/BeanStorage.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/BeanStorage.java Fri Sep 24 23:01:37 2010
@@ -20,13 +20,19 @@ package org.apache.myfaces.extensions.cd
 
 import org.apache.myfaces.extensions.cdi.core.api.provider.BeanManagerProvider;
 import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.event.UnscopeBeanEvent;
+import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.ConversationGroup;
 import org.apache.myfaces.extensions.cdi.core.impl.scope.conversation.spi.BeanEntry;
 import static org.apache.myfaces.extensions.cdi.core.impl.utils.CodiUtils.destroyBean;
 
 import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Default;
+import javax.inject.Named;
 import java.io.Serializable;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.lang.annotation.Annotation;
 
 /**
  * @author Gerhard Petracek
@@ -83,4 +89,52 @@ class BeanStorage implements Serializabl
 
         return this.beanManager;
     }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder result = new StringBuilder();
+
+        result.append(this.beanMap.size());
+        result.append(" beans:\n");
+        Bean<Serializable> bean;
+        Class<? extends Annotation> qualifierType;
+        for(BeanEntry<Serializable> beanEntry  : this.beanMap.values())
+        {
+            bean = beanEntry.getBean();
+
+            result.append("\t[bean]\n");
+            result.append("\tbean-class:\t\t\t\t");
+            result.append(bean.getBeanClass());
+            
+            result.append("\n\tcustom qualifier types: ");
+
+            boolean customQualifierFound = false;
+            for(Annotation qualifier : bean.getQualifiers())
+            {
+                qualifierType = qualifier.annotationType();
+
+                if(!
+                        (ConversationGroup.class.equals(qualifierType) ||
+                         Any.class.equals(qualifierType) ||
+                         Default.class.equals(qualifierType) ||
+                         Named.class.equals(qualifierType)))
+                {
+                    result.append("\t");
+                    result.append(qualifier.annotationType().getName());
+                    result.append("\n");
+                    customQualifierFound = true;
+                }
+            }
+
+            if(!customQualifierFound)
+            {
+                result.append("---\n");
+            }
+        }
+
+        result.append("\n*******");
+
+        return result.toString();
+    }
 }

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultConversation.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultConversation.java?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultConversation.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultConversation.java Fri Sep 24 23:01:37 2010
@@ -131,4 +131,27 @@ public class DefaultConversation impleme
     {
         return expirationEvaluator;
     }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder result = new StringBuilder();
+
+        result.append("\n*** conversation - start ***\n");
+        result.append(this.conversationKey);
+
+        result.append("\n");
+        result.append("active state: ");
+        result.append(getActiveState());
+        result.append("\n");
+
+        result.append(this.beanStorage);
+
+        result.append("\n");
+        result.append("expiration-evaluator: ");
+        result.append(this.expirationEvaluator.getClass().getName());
+        result.append("\n*** conversation - end ***");
+
+        return result.toString();
+    }
 }

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultConversationKey.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultConversationKey.java?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultConversationKey.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultConversationKey.java Fri Sep 24 23:01:37 2010
@@ -110,6 +110,10 @@ class DefaultConversationKey implements 
         {
             return false;
         }
+        if (!scopeType.equals(that.scopeType))
+        {
+            return false;
+        }
         if (qualifiers == null && that.qualifiers == null)
         {
             return true;
@@ -119,7 +123,7 @@ class DefaultConversationKey implements 
             return false;
         }
 
-        if (!qualifiers.equals(that.qualifiers))
+        if (!that.qualifiers.equals(qualifiers))
         {
             return false;
         }
@@ -130,11 +134,40 @@ class DefaultConversationKey implements 
     @Override
     public int hashCode()
     {
-        int result = groupKey.hashCode();
-        if (qualifiers != null)
+        int result = scopeType.hashCode();
+        result = 31 * result + groupKey.hashCode();
+        result = 31 * result + (qualifiers != null ? qualifiers.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder result = new StringBuilder("conversation-key\n");
+
+        result.append("\tscope:\t\t");
+        result.append(this.scopeType.getName());
+
+        result.append("\n");
+        result.append("\tgroup:\t\t");
+        result.append(this.groupKey.getName());
+
+        result.append("\n");
+        result.append("\tqualifiers:\t");
+
+        if(qualifiers != null)
         {
-            result = 31 * result + qualifiers.hashCode();
+            for(Annotation qualifier : this.qualifiers)
+            {
+                result.append(qualifier.annotationType().getName());
+                result.append(" ");
+            }
         }
-        return result;
+        else
+        {
+            result.append("---");
+        }
+
+        return result.toString();
     }
 }

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultWindowContextManager.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultWindowContextManager.java?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultWindowContextManager.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/DefaultWindowContextManager.java Fri Sep 24 23:01:37 2010
@@ -180,7 +180,7 @@ public class DefaultWindowContextManager
             return windowContextFactory.createWindowContext(windowContextId, this.jsfAwareWindowContextConfig);
         }
         
-        return new JsfWindowContext(windowContextId, this.jsfAwareWindowContextConfig);
+        return new JsfWindowContext(windowContextId, this.jsfAwareWindowContextConfig, this.projectStageDevelopment);
     }
 
     public boolean activateWindowContext(String windowContextId)

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/JsfWindowContext.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/JsfWindowContext.java?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/JsfWindowContext.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/JsfWindowContext.java Fri Sep 24 23:01:37 2010
@@ -20,6 +20,7 @@ package org.apache.myfaces.extensions.cd
 
 import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.Conversation;
 import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.WindowContextConfig;
+import static org.apache.myfaces.extensions.cdi.core.impl.utils.CodiUtils.isQualifierEqual;
 import org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation.spi.EditableConversation;
 import org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation.spi.EditableWindowContext;
 import org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation.spi.ConversationKey;
@@ -29,6 +30,7 @@ import org.apache.myfaces.extensions.cdi
 import org.apache.myfaces.extensions.cdi.jsf.impl.util.JsfUtils;
 import static org.apache.myfaces.extensions.cdi.jsf.impl.util.ConversationUtils.convertToScope;
 import static org.apache.myfaces.extensions.cdi.jsf.impl.util.ExceptionUtils.conversationNotEditableException;
+import static org.apache.myfaces.extensions.cdi.jsf.impl.util.ExceptionUtils.conversationNotFoundException;
 
 import javax.enterprise.inject.Typed;
 import java.util.Date;
@@ -37,6 +39,7 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.HashSet;
+import java.util.logging.Logger;
 import java.util.concurrent.ConcurrentHashMap;
 import java.lang.annotation.Annotation;
 
@@ -53,6 +56,7 @@ public class JsfWindowContext implements
     private final String id;
 
     private final JsfAwareWindowContextConfig jsfAwareWindowContextConfig;
+    private final boolean projectStageDevelopment;
 
     private Map<ConversationKey, EditableConversation> groupedConversations
             = new ConcurrentHashMap<ConversationKey, EditableConversation>();
@@ -61,10 +65,14 @@ public class JsfWindowContext implements
 
     private final TimeoutExpirationEvaluator expirationEvaluator;
 
-    JsfWindowContext(String windowContextId, JsfAwareWindowContextConfig jsfAwareWindowContextConfig)
+    JsfWindowContext(String windowContextId,
+                     JsfAwareWindowContextConfig jsfAwareWindowContextConfig,
+                     boolean projectStageDevelopment)
     {
         this.id = windowContextId;
         this.jsfAwareWindowContextConfig = jsfAwareWindowContextConfig;
+        this.projectStageDevelopment = projectStageDevelopment;
+
         this.expirationEvaluator = new TimeoutExpirationEvaluator(
                 this.jsfAwareWindowContextConfig.getWindowContextTimeoutInMinutes());
     }
@@ -76,16 +84,16 @@ public class JsfWindowContext implements
 
     public void closeConversations()
     {
-        endConversations(false);
+        closeConversations(false);
     }
 
     public void close()
     {
-        endConversations(true);
+        closeConversations(true);
         this.attributes.clear();
     }
 
-    public synchronized void endConversations(boolean forceEnd)
+    public synchronized void closeConversations(boolean forceEnd)
     {
         for (Map.Entry<ConversationKey, EditableConversation> conversationEntry : this.groupedConversations.entrySet())
         {
@@ -105,7 +113,7 @@ public class JsfWindowContext implements
 
         if(conversation == null)
         {
-            conversation = this.groupedConversations.get(conversationKey);
+            conversation = getConversationForKey(conversationKey, false);
 
             //TODO
             if (conversation != null && !conversation.isActive())
@@ -132,7 +140,7 @@ public class JsfWindowContext implements
         ConversationKey conversationKey =
                 new DefaultConversationKey(scopeType, conversationGroupKey, qualifiers);
 
-        Conversation conversation = this.groupedConversations.get(conversationKey);
+        Conversation conversation = getConversationForKey(conversationKey, true);
 
         if(!(conversation instanceof EditableConversation))
         {
@@ -159,20 +167,29 @@ public class JsfWindowContext implements
                                                           EditableConversation conversation,
                                                           boolean forceEnd)
     {
-        if (forceEnd)
-        {
-            conversation.close();
-            return this.groupedConversations.remove(conversationKey);
-        }
-        else if(conversation instanceof EditableConversation)
-        {
-            conversation.deactivate();
+        logInformationAboutConversations("before JsfWindowContext#endAndRemoveConversation");
 
-            if(!conversation.isActive())
+        try
+        {
+            if (forceEnd)
             {
                 conversation.close();
                 return this.groupedConversations.remove(conversationKey);
             }
+            else
+            {
+                conversation.deactivate();
+
+                if(!conversation.isActive())
+                {
+                    conversation.close();
+                    return this.groupedConversations.remove(conversationKey);
+                }
+            }
+        }
+        finally
+        {
+            logInformationAboutConversations("after JsfWindowContext#endAndRemoveConversation");
         }
 
         return null;
@@ -256,4 +273,109 @@ public class JsfWindowContext implements
         //noinspection unchecked
         return (T)this.attributes.get(name);
     }
+
+    private EditableConversation getConversationForKey(ConversationKey conversationKey, boolean existingConversation)
+    {
+        EditableConversation editableConversation = this.groupedConversations.get(conversationKey);
+
+        if(editableConversation != null)
+        {
+            return editableConversation;
+        }
+
+        if(!existingConversation)
+        {
+            return null;
+        }
+
+        if(conversationKey.getQualifiers() != null)
+        {
+            //we have to manually recalculate the the conversation keys due to the restrictions of annotations
+            //we don't do that per default because in most use-cases you don't need qualifiers
+            //that means most use-cases will have a better performance and only very few will have an overhead as soon
+            //as a conversation gets closed manually
+            editableConversation = getConversationForDynamicKey(conversationKey);
+        }
+
+        if(editableConversation != null)
+        {
+            return editableConversation;
+        }
+
+        throw conversationNotFoundException(conversationKey.toString());
+    }
+
+    private EditableConversation getConversationForDynamicKey(ConversationKey conversationKey)
+    {
+        for(Map.Entry<ConversationKey, EditableConversation> conversationEntry : this.groupedConversations.entrySet())
+        {
+            if(isSameConversationType(conversationEntry.getKey(), conversationKey))
+            {
+                if(compareAnnotations(conversationEntry.getKey().getQualifiers(), conversationKey.getQualifiers()))
+                {
+                    return conversationEntry.getValue();
+                }
+            }
+
+        }
+
+        return null;
+    }
+
+    private boolean isSameConversationType(ConversationKey currentConversationKey, ConversationKey conversationKey)
+    {
+        return currentConversationKey.getConversationGroup().equals(conversationKey.getConversationGroup()) &&
+                currentConversationKey.getScope().equals(conversationKey.getScope());
+    }
+
+    private boolean compareAnnotations(Set<Annotation> source, Set<Annotation> target)
+    {
+        Set<Annotation> sourceAnnotations = new HashSet<Annotation>(source);
+        Set<Annotation> targetAnnotations = new HashSet<Annotation>(target);
+
+        Iterator<Annotation> sourceAnnotationIterator = sourceAnnotations.iterator();
+        Iterator<Annotation> targetAnnotationIterator = targetAnnotations.iterator();
+
+        Annotation sourceAnnotation;
+        Annotation targetAnnotation;
+
+        while(sourceAnnotationIterator.hasNext())
+        {
+            sourceAnnotation = sourceAnnotationIterator.next();
+
+            while (targetAnnotationIterator.hasNext())
+            {
+                targetAnnotation = targetAnnotationIterator.next();
+
+                if(isQualifierEqual(sourceAnnotation, targetAnnotation))
+                {
+                    sourceAnnotationIterator.remove();
+                    targetAnnotationIterator.remove();
+                }
+            }
+        }
+
+        return sourceAnnotations.isEmpty() && targetAnnotations.isEmpty();
+    }
+
+    public void logInformationAboutConversations(String label)
+    {
+        if(!this.projectStageDevelopment)
+        {
+            return;
+        }
+
+        Logger logger = Logger.getLogger(JsfWindowContext.class.getName());
+        logger.info(label);
+        logger.info("\n*** conversations - start ***");
+        for(Map.Entry<ConversationKey, EditableConversation> conversationEntry : this.groupedConversations.entrySet())
+        {
+            if(conversationEntry.getValue() instanceof DefaultConversation)
+            {
+                logger.info(conversationEntry.getValue().toString());
+            }
+        }
+        logger.info("\n\n*** conversations - end ***");
+        logger.info("***************************");
+    }
 }

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ExceptionUtils.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ExceptionUtils.java?rev=1001103&r1=1001102&r2=1001103&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ExceptionUtils.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/util/ExceptionUtils.java Fri Sep 24 23:01:37 2010
@@ -83,4 +83,9 @@ public class ExceptionUtils
                 "If you really need it, use an phases-observer-method e.g.: " +
                 "protected void preRestoreView(@Observes @BeforePhase(PhaseId.RESTORE_VIEW) PhaseEvent event) ");
     }
+
+    public static IllegalArgumentException conversationNotFoundException(String conversationKey)
+    {
+        return new IllegalArgumentException("Cannot find conversation with key: " + conversationKey);
+    }
 }