You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/07/08 17:26:25 UTC

svn commit: r674858 - /myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java

Author: skitching
Date: Tue Jul  8 08:26:25 2008
New Revision: 674858

URL: http://svn.apache.org/viewvc?rev=674858&view=rev
Log:
* remove methods getConversationContexts() and
startNewConversationContext(). Note that these methods have NOT been
in any orchestra core release.
* add method createConversationContext(parent)
* add removeAndInvalidateConversationContext(context)
* don't time out contexts that have child contexts.

Modified:
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java

Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java?rev=674858&r1=674857&r2=674858&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java Tue Jul  8 08:26:25 2008
@@ -22,6 +22,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.orchestra.frameworkAdapter.FrameworkAdapter;
+import org.apache.myfaces.orchestra.lib.OrchestraException;
 import org.apache.myfaces.orchestra.requestParameterProvider.RequestParameterProviderManager;
 
 import java.io.IOException;
@@ -53,8 +54,6 @@
     private final static String CONVERSATION_MANAGER_KEY = "org.apache.myfaces.ConversationManager";
     private final static String CONVERSATION_CONTEXT_REQ = "org.apache.myfaces.ConversationManager.conversationContext";
 
-    private final static ConversationContext[] EMPTY_CONTEXTS = new ConversationContext[0];
-
     private static final Iterator EMPTY_ITERATOR = Collections.EMPTY_LIST.iterator();
 
     private final Log log = LogFactory.getLog(ConversationManager.class);
@@ -222,48 +221,6 @@
     }
 
     /**
-     * Return a snapshot array of all conversation contexts associated with the
-     * current topmost conversation context.
-     * 
-     * @since 1.2
-    protected ConversationContext[] getConversationContexts()
-    {
-        synchronized (this)
-        {
-            List ret = new ArrayList();
-
-            ConversationContext topmost = getTopmostConversationContext();
-            if (topmost == null)
-            {
-                return EMPTY_CONTEXTS;
-            }
-
-            Iterator iterConversationContexts = conversationContexts.values().iterator();
-            while (iterConversationContexts.hasNext())
-            {
-                ConversationContext conversationContext = (ConversationContext) iterConversationContexts.next();
-                if (conversationContext.getParent() == null)
-                {
-                    // this is a topmost conversation context already
-                    continue;
-                }
-
-                if (topmost != conversationContext.getTopmostConversationContext())
-                {
-                    continue;
-                }
-
-                ret.add(conversationContext);
-            }
-
-            ConversationContext[] contexts = new ConversationContext[ret.size()];
-            ret.toArray(contexts);
-            return contexts;
-        }
-    }
-     */
-
-    /**
      * Get the conversation context for the given id.
      * <p>
      * Null is returned if there is no ConversationContext with the specified id.
@@ -306,37 +263,26 @@
     }
 
     /**
-     * This will start a new conversation context using the current conversation context as the parent.
-     * If there is no parent a topmost conversation context will be created.
-     * The returned conversation context is then a child of this automatically created conversation context.
-     * <br />
-     * Notice: The created conversation context is not activated after this method call. You have to call
-     * {@link #activateConversationContext(ConversationContext)} on the newly create context too.
+     * This will create a new conversation context using the specified context as
+     * its parent. 
+     * <p>
+     * The returned context is not selected as the "current" one; see activateConversationContext.
      * 
-     * @since 1.2
-    protected ConversationContext startNewConversationContext()
+     * @since 1.3
+     */
+    public ConversationContext createConversationContext(ConversationContext parent)
     {
-        synchronized (this)
-        {
-            ConversationContext parent = getCurrentConversationContext();
-            if (parent == null)
-            {
-                parent = getOrCreateTopmostConversationContext();
-            }
-
-            Long conversationContextId = createNextConversationContextId();
-
-            ConversationContext conversationContext = (ConversationContext) conversationContexts.get(conversationContextId);
-            if (conversationContext == null)
-            {
-                conversationContext = new ConversationContext(parent, conversationContextId);
-                conversationContexts.put(conversationContextId, conversationContext);
-            }
+        Long ctxId = createNextConversationContextId();
+        ConversationContext ctx = new ConversationContext(parent, ctxId.longValue());
 
-            return conversationContext;
+        synchronized(this)
+        {
+            conversationContexts.put(ctxId, ctx);
         }
+        
+        return ctx;
     }
-*/
+
     /**
      * Make the specific context the current context for the current HTTP session.
      * <p>
@@ -362,15 +308,69 @@
             ConversationContext conversationContext = getConversationContext(conversationContextId);
             if (conversationContext != null)
             {
-                conversationContext.clear();
+                conversationContext.invalidate();
             }
         }
     }
 
     /**
-     * Destroy the given conversation context.
+     * Removes the specified contextId from the set of known contexts,
+     * and deletes every conversation in it.
+     * <p>
+     * Objects in the conversation which implement ConversationAware
+     * will have callbacks invoked.
      * <p>
-     * Note: it is assumed that the context is already been destroyed
+     * The conversation being removed must not be the currently active
+     * context. If it is, then method activateConversationContext should
+     * first be called on some other instance (perhaps the parent of the
+     * one being removed) before this method is called.
+     * 
+     * @since 1.3
+     */
+    public void removeAndInvalidateConversationContext(ConversationContext context)
+    {
+        if (context.hasChildren())
+        {
+            throw new OrchestraException("Cannot remove context with children");
+        }
+
+        if (context.getIdAsLong().equals(findConversationContextId()))
+        {
+            throw new OrchestraException("Cannot remove current context");
+        }
+
+        synchronized(conversationContexts)
+        {
+            conversationContexts.remove(context.getIdAsLong());
+        }
+
+        ConversationContext parent = context.getParent();
+        if (parent != null)
+        {
+            parent.removeChild(context);
+        }
+
+        context.invalidate();
+        
+        // TODO: add the deleted context ids to a list stored in the session,
+        // and redirect to an error page if any future request specifies this id.
+        // This catches things like going "back" into a flow that has ended, or
+        // navigating with the parent page of a popup flow (which kills the popup
+        // flow context) then trying to use the popup page.
+        //
+        // We cannot simply report an error for every case where an invalid id is
+        // used, because bookmarks will have ids in them; when the bookmark is used
+        // after the session has died we still want the bookmark url to work. Possibly
+        // we should allow GET with a bad id, but always fail a POST with one?
+    }
+
+    /**
+     * Removes the specified contextId from the set of known contexts.
+     * <p>
+     * It does nothing else. Maybe it should be called "detachConversationContext"
+     * or similar.
+     * 
+     * @deprecated This method is not actually used by anything.
      */
     protected void removeConversationContext(Long conversationContextId)
     {
@@ -567,8 +567,13 @@
         {
             Map.Entry context = contexts[i];
 
-            Long conversationContextId = (Long) context.getKey();
             ConversationContext conversationContext = (ConversationContext) context.getValue();
+            if (conversationContext.hasChildren())
+            {
+                // Never time out contexts that have children. Let the children time out first...
+                continue;
+            }
+
             conversationContext.checkConversationTimeout();
 
             if (conversationContext.getTimeout() > -1 &&
@@ -580,11 +585,7 @@
                     log.debug("end conversation context due to timeout: " + conversationContext.getId());
                 }
 
-                conversationContext.clear();
-                synchronized (this)
-                {
-                    conversationContexts.remove(conversationContextId);
-                }
+                removeAndInvalidateConversationContext(conversationContext);
             }
         }
     }