You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by im...@apache.org on 2008/04/05 16:42:15 UTC
svn commit: r645109 - in
/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra:
conversation/ lib/jsf/
Author: imario
Date: Sat Apr 5 07:42:13 2008
New Revision: 645109
URL: http://svn.apache.org/viewvc?rev=645109&view=rev
Log:
ORCHESTRA-19: First draft which should allow one to start child conversation context as required by dialog frameworks or e.g. if one would like to have contexts one can programmatically start/stop/pause/restart
Modified:
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/Conversation.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationContext.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationRequestParameterProvider.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/ContextLockRequestHandler.java
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/Conversation.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/Conversation.java?rev=645109&r1=645108&r2=645109&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/Conversation.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/Conversation.java Sat Apr 5 07:42:13 2008
@@ -364,7 +364,7 @@
}
// see if there is a single conversation hanging around in the conversation context
- ConversationContext cctx = ConversationManager.getInstance().getCurrentConversationContext(false);
+ ConversationContext cctx = ConversationManager.getInstance().getCurrentConversationContext();
if (cctx != null)
{
return cctx.getConversation(SpringSingleConversationScope.CONVERSATION_NAME);
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationContext.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationContext.java?rev=645109&r1=645108&r2=645109&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationContext.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationContext.java Sat Apr 5 07:42:13 2008
@@ -19,15 +19,15 @@
package org.apache.myfaces.orchestra.conversation;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.orchestra.lib._ReentrantLock;
+
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.myfaces.orchestra.lib._ReentrantLock;
-
/**
* A ConversationContext is a container for a set of conversations.
* <p>
@@ -44,44 +44,80 @@
// This id is attached as a query parameter to every url rendered in a page
// (forms and links) so that if that url is invoked then the request will
- // cause the same context to be used from the user's http session.
- private final long id;
+ // cause the same context to be used from the user's http session.
+ private final Long id;
// See addAttribute
private final Map attributes = new TreeMap();
+ // the parent conversation context
+ private final ConversationContext parent;
+
// The conversations held by this context, keyed by conversation name.
private final Map conversations = new TreeMap();
+ /**
+ * A name associated with this context
+ */
+ private String name;
+
// time at which this was last accessed, used for timeouts.
private long lastAccess;
// default timeout for contexts: 30 minutes.
private long timeoutMillis = 30 * 60 * 1000;
-
+
private final _ReentrantLock lock = new _ReentrantLock();
- protected ConversationContext(long id)
+ protected ConversationContext(ConversationContext parent, Long id)
{
+ this.parent = parent;
this.id = id;
touch();
}
/**
+ * get the name associated to this context
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * a name associated with this context
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
* The conversation context id, unique within the current http session.
*/
- public long getId()
+ public Long getId()
{
return id;
}
/**
+ * The parent conversation context
+ */
+ public ConversationContext getParent()
+ {
+ return parent;
+ }
+
+ /**
* Mark this context as having been used.
*/
protected void touch()
{
lastAccess = System.currentTimeMillis();
+
+ if (getParent() != null)
+ {
+ getParent().touch();
+ }
}
/**
@@ -153,7 +189,7 @@
/**
* Remove the conversation from this context.
- *
+ *
* <p>Notice: It is assumed that the conversation has already been invalidated.</p>
*/
protected void removeConversation(Conversation conversation)
@@ -167,7 +203,7 @@
/**
* Remove the conversation with the given name from this context.
- *
+ *
* <p>Notice: Its assumed that the conversation has already been invalidated</p>
*/
protected void removeConversation(String name)
@@ -323,7 +359,7 @@
return attributes.remove(name);
}
}
-
+
/**
* Block until no other thread has this instance marked as reserved, then
* mark the object as reserved for this thread.
@@ -333,32 +369,47 @@
* If this method is called, then an equal number of calls to
* unlockForCurrentThread <b>MUST</b> made, or this context object
* will remain locked until the http session times out.
- *
+ *
* @since 1.1
*/
public void lockInterruptablyForCurrentThread() throws InterruptedException
{
lock.lockInterruptibly();
}
-
+
/**
* Block until no other thread has this instance marked as reserved, then
- * mark the object as reserved for this thread.
- *
+ * mark the object as reserved for this thread.
+ *
* @since 1.1
*/
public void unlockForCurrentThread()
{
lock.unlock();
}
-
+
/**
* Return true if this object is currently locked by the calling thread.
- *
+ *
* @since 1.1
*/
public boolean isLockedForCurrentThread()
{
return lock.isHeldByCurrentThread();
+ }
+
+ /**
+ * get the topmost conversation context this conversation context is associated with
+ * @return
+ */
+ public ConversationContext getTopmostConversationContext() {
+
+ ConversationContext cctx = this;
+ while (cctx != null && cctx.getParent() != null)
+ {
+ cctx = getParent();
+ }
+
+ return cctx;
}
}
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=645109&r1=645108&r2=645109&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 Sat Apr 5 07:42:13 2008
@@ -27,9 +27,11 @@
import java.io.IOException;
import java.io.ObjectStreamException;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
/**
@@ -53,6 +55,8 @@
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);
@@ -159,11 +163,7 @@
}
else
{
- synchronized(this)
- {
- conversationContextId = new Long(nextConversationContextId);
- nextConversationContextId++;
- }
+ conversationContextId = createNextConversationContextId();
}
fa.setRequestAttribute(CONVERSATION_CONTEXT_REQ, conversationContextId);
@@ -172,6 +172,16 @@
return conversationContextId;
}
+ protected Long createNextConversationContextId() {
+ Long conversationContextId;
+ synchronized(this)
+ {
+ conversationContextId = new Long(nextConversationContextId);
+ nextConversationContextId++;
+ }
+ return conversationContextId;
+ }
+
/**
* Get the conversation context for the given id
*/
@@ -184,17 +194,79 @@
}
/**
+ * Return a snapshot array of all conversation contexts associated with the
+ * current topmost conversation context.
+ */
+ protected ConversationContext[] getConversationContexts()
+ {
+ synchronized (this)
+ {
+ List ret = new ArrayList();
+
+ ConversationContext topmost = getTopmostConversationContext(false);
+ 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. <br />
- * If there is no conversation context a new one will be created
+ * If there is no conversation context a new one will be created. The new conversation context
+ * will be a "top-level" context.
*/
- protected ConversationContext getOrCreateConversationContext(Long conversationContextId)
+ protected ConversationContext createConversationContext(Long conversationContextId)
+ {
+ return new ConversationContext(null, conversationContextId);
+ }
+
+ /**
+ * 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.
+ */
+ protected ConversationContext startNewConversationContext()
{
synchronized (this)
{
+ ConversationContext parent = getCurrentConversationContext();
+ if (parent == null)
+ {
+ parent = getTopmostConversationContext(true);
+ }
+
+ Long conversationContextId = createNextConversationContextId();
+
ConversationContext conversationContext = (ConversationContext) conversationContexts.get(conversationContextId);
if (conversationContext == null)
{
- conversationContext = new ConversationContext(conversationContextId.longValue());
+ conversationContext = new ConversationContext(parent, conversationContextId);
conversationContexts.put(conversationContextId, conversationContext);
}
@@ -203,6 +275,16 @@
}
/**
+ * Actually activate the given conversation context. This means the current conversation context will be
+ * deactivated and the conversations of the passed in conversation context are those used again.
+ */
+ public void activateConversationContext(ConversationContext ctx)
+ {
+ FrameworkAdapter fa = FrameworkAdapter.getCurrentInstance();
+ fa.setRequestAttribute(CONVERSATION_CONTEXT_REQ, ctx.getId());
+ }
+
+ /**
* Ends all conversations within the current context; the context itself will remain active.
*/
public void clearCurrentConversationContext()
@@ -235,7 +317,11 @@
*/
public Conversation startConversation(String name, ConversationFactory factory)
{
- ConversationContext conversationContext = getCurrentConversationContext(true);
+ ConversationContext conversationContext = getCurrentConversationContext();
+ if (conversationContext == null)
+ {
+ conversationContext = getTopmostConversationContext(true);
+ }
return conversationContext.startConversation(name, factory);
}
@@ -300,17 +386,41 @@
}
/**
- * Get the current conversation context.
+ * Get the current conversation context. In an plain Orchestra installation this will also be the tompost
+ * conversation context. When using a dialog/page-flow environment this might be the bottom conversation context.
*/
- public ConversationContext getCurrentConversationContext(boolean create)
+ public ConversationContext getCurrentConversationContext()
{
Long conversationContextId = getConversationContextId();
- ConversationContext conversationContext = getConversationContext(conversationContextId);
- if (conversationContext == null && create)
+ return getConversationContext(conversationContextId);
+ }
+
+ /**
+ * Get the topmost conversation context (aka the window conversation context).
+ */
+ public ConversationContext getTopmostConversationContext(boolean create)
+ {
+ Long conversationContextId = getConversationContextId();
+ synchronized (this)
{
- conversationContext = getOrCreateConversationContext(conversationContextId);
+ ConversationContext conversationContext = getConversationContext(conversationContextId);
+ while (conversationContext != null && conversationContext.getParent() != null)
+ {
+ conversationContext = conversationContext.getParent();
+ }
+ if (conversationContext == null && create)
+ {
+ conversationContext = (ConversationContext) conversationContexts.get(conversationContextId);
+ if (conversationContext == null)
+ {
+ conversationContext = createConversationContext(conversationContextId);
+ conversationContexts.put(conversationContextId, conversationContext);
+ }
+
+ return conversationContext;
+ }
+ return conversationContext;
}
- return conversationContext;
}
/**
@@ -318,9 +428,9 @@
*
* @return null if there is no context active
*/
- public ConversationContext getCurrentConversationContext()
+ public ConversationContext getTopmostConversationContext()
{
- return getCurrentConversationContext(false);
+ return getTopmostConversationContext(false);
}
/**
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationRequestParameterProvider.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationRequestParameterProvider.java?rev=645109&r1=645108&r2=645109&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationRequestParameterProvider.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationRequestParameterProvider.java Sat Apr 5 07:42:13 2008
@@ -83,9 +83,13 @@
throw new IllegalStateException("can find the conversationManager");
}
- ConversationContext ctx = conversationManager.getCurrentConversationContext(true);
+ ConversationContext ctx = conversationManager.getCurrentConversationContext();
+ if (ctx == null)
+ {
+ ctx = conversationManager.getTopmostConversationContext(true);
+ }
- return Long.toString(ctx.getId(), Character.MAX_RADIX);
+ return Long.toString(ctx.getId().longValue(), Character.MAX_RADIX);
}
public String[] getFields()
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/ContextLockRequestHandler.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/ContextLockRequestHandler.java?rev=645109&r1=645108&r2=645109&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/ContextLockRequestHandler.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/ContextLockRequestHandler.java Sat Apr 5 07:42:13 2008
@@ -48,7 +48,11 @@
ConversationManager manager = ConversationManager.getInstance(false);
if (manager != null)
{
- context = manager.getCurrentConversationContext(true);
+ context = manager.getCurrentConversationContext();
+ if (context == null)
+ {
+ context = manager.getTopmostConversationContext(true);
+ }
try
{
context.lockInterruptablyForCurrentThread();