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/02/21 21:32:43 UTC
svn commit: r629975 [1/4] - in
/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation:
./ basic/ spring/
Author: skitching
Date: Thu Feb 21 12:32:37 2008
New Revision: 629975
URL: http://svn.apache.org/viewvc?rev=629975&view=rev
Log:
Tab to spaces only
Modified:
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/AccessScopeManager.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/AccessScopeManagerConfiguration.java
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/ConversationAccessLifetimeAspect.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAware.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationBindingEvent.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationBindingListener.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/ConversationFactory.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/ConversationMessager.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/conversation/ConversationTimeoutableAspect.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationUtils.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationWiperThread.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/CurrentConversationAdvice.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/CurrentConversationInfo.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/FlashScopeManager.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/_ConversationUtils.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/basic/LogConversationMessager.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/AbstractSpringOrchestraScope.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/BeanDefinitionConversationNameAttrDecorator.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/JpaPersistenceContextFactory.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/OrchestraAdvisorBeanPostProcessor.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/OrchestraNamespaceHandler.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/PersistenceContextCloser.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/PersistenceContextConversationInterceptor.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/PersistenceContextFactory.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/ScopedBeanTargetSource.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringConversationScope.java
myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/_SpringUtils.java
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/AccessScopeManager.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/AccessScopeManager.java?rev=629975&r1=629974&r2=629975&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/AccessScopeManager.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/AccessScopeManager.java Thu Feb 21 12:32:37 2008
@@ -36,136 +36,136 @@
*/
public class AccessScopeManager
{
- private static final Log log = LogFactory.getLog(AccessScopeManager.class);
- private static final String REQ_ATTR_KEY = AccessScopeManager.class.getName();
- private AccessScopeManagerConfiguration accessScopeManagerConfiguration;
-
- private boolean recordAccess;
- private boolean ignoreRequest;
- private Set accessedConversations = new HashSet();
-
- public static AccessScopeManager getInstance()
- {
- // Get the instance by looking up a variable whose name is this class name, using the normal
- // managed bean lookup process. When an IOC framework like Spring is being used to extend
- // the standard JSF managed bean declaration facilities, then the bean may be retrieved
- // from there.
- //
- // Using a lookup of a managed bean allows the user to set configuration properties on the
- // manager class and its properties.
-
- FrameworkAdapter fa = FrameworkAdapter.getCurrentInstance();
- AccessScopeManager manager = (AccessScopeManager) fa.getRequestAttribute(REQ_ATTR_KEY);
- if (manager != null)
- {
- // already found and cached in request attributes
- return manager;
- }
-
- // Backwards compatibility hack: look for FlashScopeManager. It is possible that
- // a user of Orchestra 1.0 has copied the declaration from the original Orchestra
- // config file into their own code to inject special settings.
- manager = (AccessScopeManager) fa.getBean(FlashScopeManager.class.getName());
- if (manager != null)
- {
- log.info("found FlashScopeManager object");
- fa.setRequestAttribute(REQ_ATTR_KEY, manager);
- return manager;
- }
-
- // Backwards compatibility hack: look for FlashScopeManagerConfiguration. It is
- // possible that a user of Orchestra 1.0 has overridden just the Configuration
- // bit to set their own ignoredViewId values (as recommended!):
- //
- // This is a little dodgy as settings made through the new AccessScopeManage
- // bean will will now be silently ignored.
- FlashScopeManagerConfiguration cfg = (FlashScopeManagerConfiguration) fa.getBean(FlashScopeManagerConfiguration.class.getName());
- if (cfg != null)
- {
- log.info("found FlashScopeManagerConfiguration object");
- manager = new AccessScopeManager();
- manager.setAccessScopeManagerConfiguration(cfg);
- fa.setRequestAttribute(REQ_ATTR_KEY, manager);
- return manager;
- }
-
- // normal case
- manager = (AccessScopeManager) fa.getBean(AccessScopeManager.class.getName());
- if (manager != null)
- {
- log.info("found AccessScopeManager object");
- fa.setRequestAttribute(REQ_ATTR_KEY, manager);
- return manager;
- }
-
- // TODO: Make this error message less spring-specific. Spring is not the only IOC container
- // that Orchestra can be used with.
- throw new IllegalArgumentException(
- "No AccessScopeManager found. Probably you forgot to add "
- + "<import resource=\"classpath*:/META-INF/spring-orchestra-init.xml\" />"
- + " to your spring configuration.");
- }
-
- public AccessScopeManagerConfiguration getAccessScopeManagerConfiguration()
- {
- return accessScopeManagerConfiguration;
- }
-
- public void setAccessScopeManagerConfiguration(AccessScopeManagerConfiguration accessScopeManagerConfiguration)
- {
- this.accessScopeManagerConfiguration = accessScopeManagerConfiguration;
- }
-
- /**
- * This is invoked at the point in the request lifecycle after which we want to
- * start tracking use of access-scoped objects.
- */
- public void beginRecording()
- {
- recordAccess = true;
- }
-
- /**
- * Add a conversation to the list of accessed conversations.
- * <p>
- * This method is expected to be called via AOP proxies wrapped around each conversation-scoped
- * bean; any invocation of a method on such a bean causes the conversation associated with that
- * bean to be added to the accessed list here.
- */
- public void addConversationAccess(String conversationName)
- {
- // Don't bother tracking accessed conversations if we will never use the data.
- // Otherwise, add this conversation name to the list of accessed conversations.
- if (recordAccess && !ignoreRequest && !accessedConversations.contains(conversationName))
- {
- accessedConversations.add(conversationName);
- }
- }
-
- public boolean isIgnoreRequest()
- {
- return ignoreRequest;
- }
-
- /**
- * Suppress access scope for the current request, ie do not terminate conversations that are
- * not accessed by this request.
- * <p>
- * This can come in useful occasionally, particularly when handling AJAX requests which
- * only access some of the beans associated with the current view.
- */
- public void setIgnoreRequest()
- {
- this.ignoreRequest = true;
- }
-
- public boolean isConversationAccessed(String name)
- {
- if (ignoreRequest)
- {
- throw new IllegalStateException();
- }
+ private static final Log log = LogFactory.getLog(AccessScopeManager.class);
+ private static final String REQ_ATTR_KEY = AccessScopeManager.class.getName();
+ private AccessScopeManagerConfiguration accessScopeManagerConfiguration;
+
+ private boolean recordAccess;
+ private boolean ignoreRequest;
+ private Set accessedConversations = new HashSet();
+
+ public static AccessScopeManager getInstance()
+ {
+ // Get the instance by looking up a variable whose name is this class name, using the normal
+ // managed bean lookup process. When an IOC framework like Spring is being used to extend
+ // the standard JSF managed bean declaration facilities, then the bean may be retrieved
+ // from there.
+ //
+ // Using a lookup of a managed bean allows the user to set configuration properties on the
+ // manager class and its properties.
+
+ FrameworkAdapter fa = FrameworkAdapter.getCurrentInstance();
+ AccessScopeManager manager = (AccessScopeManager) fa.getRequestAttribute(REQ_ATTR_KEY);
+ if (manager != null)
+ {
+ // already found and cached in request attributes
+ return manager;
+ }
+
+ // Backwards compatibility hack: look for FlashScopeManager. It is possible that
+ // a user of Orchestra 1.0 has copied the declaration from the original Orchestra
+ // config file into their own code to inject special settings.
+ manager = (AccessScopeManager) fa.getBean(FlashScopeManager.class.getName());
+ if (manager != null)
+ {
+ log.info("found FlashScopeManager object");
+ fa.setRequestAttribute(REQ_ATTR_KEY, manager);
+ return manager;
+ }
+
+ // Backwards compatibility hack: look for FlashScopeManagerConfiguration. It is
+ // possible that a user of Orchestra 1.0 has overridden just the Configuration
+ // bit to set their own ignoredViewId values (as recommended!):
+ //
+ // This is a little dodgy as settings made through the new AccessScopeManage
+ // bean will will now be silently ignored.
+ FlashScopeManagerConfiguration cfg = (FlashScopeManagerConfiguration) fa.getBean(FlashScopeManagerConfiguration.class.getName());
+ if (cfg != null)
+ {
+ log.info("found FlashScopeManagerConfiguration object");
+ manager = new AccessScopeManager();
+ manager.setAccessScopeManagerConfiguration(cfg);
+ fa.setRequestAttribute(REQ_ATTR_KEY, manager);
+ return manager;
+ }
+
+ // normal case
+ manager = (AccessScopeManager) fa.getBean(AccessScopeManager.class.getName());
+ if (manager != null)
+ {
+ log.info("found AccessScopeManager object");
+ fa.setRequestAttribute(REQ_ATTR_KEY, manager);
+ return manager;
+ }
+
+ // TODO: Make this error message less spring-specific. Spring is not the only IOC container
+ // that Orchestra can be used with.
+ throw new IllegalArgumentException(
+ "No AccessScopeManager found. Probably you forgot to add "
+ + "<import resource=\"classpath*:/META-INF/spring-orchestra-init.xml\" />"
+ + " to your spring configuration.");
+ }
+
+ public AccessScopeManagerConfiguration getAccessScopeManagerConfiguration()
+ {
+ return accessScopeManagerConfiguration;
+ }
+
+ public void setAccessScopeManagerConfiguration(AccessScopeManagerConfiguration accessScopeManagerConfiguration)
+ {
+ this.accessScopeManagerConfiguration = accessScopeManagerConfiguration;
+ }
+
+ /**
+ * This is invoked at the point in the request lifecycle after which we want to
+ * start tracking use of access-scoped objects.
+ */
+ public void beginRecording()
+ {
+ recordAccess = true;
+ }
+
+ /**
+ * Add a conversation to the list of accessed conversations.
+ * <p>
+ * This method is expected to be called via AOP proxies wrapped around each conversation-scoped
+ * bean; any invocation of a method on such a bean causes the conversation associated with that
+ * bean to be added to the accessed list here.
+ */
+ public void addConversationAccess(String conversationName)
+ {
+ // Don't bother tracking accessed conversations if we will never use the data.
+ // Otherwise, add this conversation name to the list of accessed conversations.
+ if (recordAccess && !ignoreRequest && !accessedConversations.contains(conversationName))
+ {
+ accessedConversations.add(conversationName);
+ }
+ }
+
+ public boolean isIgnoreRequest()
+ {
+ return ignoreRequest;
+ }
+
+ /**
+ * Suppress access scope for the current request, ie do not terminate conversations that are
+ * not accessed by this request.
+ * <p>
+ * This can come in useful occasionally, particularly when handling AJAX requests which
+ * only access some of the beans associated with the current view.
+ */
+ public void setIgnoreRequest()
+ {
+ this.ignoreRequest = true;
+ }
+
+ public boolean isConversationAccessed(String name)
+ {
+ if (ignoreRequest)
+ {
+ throw new IllegalStateException();
+ }
- return accessedConversations.contains(name);
- }
+ return accessedConversations.contains(name);
+ }
}
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/AccessScopeManagerConfiguration.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/AccessScopeManagerConfiguration.java?rev=629975&r1=629974&r2=629975&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/AccessScopeManagerConfiguration.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/AccessScopeManagerConfiguration.java Thu Feb 21 12:32:37 2008
@@ -30,23 +30,23 @@
*/
public class AccessScopeManagerConfiguration
{
- private Set ignoreViewIds;
+ private Set ignoreViewIds;
- public Set getIgnoreViewIds()
- {
- return ignoreViewIds;
- }
+ public Set getIgnoreViewIds()
+ {
+ return ignoreViewIds;
+ }
- /**
- * Do not terminate any "unaccessed conversations" after handling a request to
- * any of the specified views.
- *
- * Special "ignored views" are useful when dealing with things like nested
- * frames within a page that periodically refresh themselves while the "main"
- * part of the page remains unsubmitted.
- */
- public void setIgnoreViewIds(Set ignoreViewIds)
- {
- this.ignoreViewIds = ignoreViewIds;
- }
+ /**
+ * Do not terminate any "unaccessed conversations" after handling a request to
+ * any of the specified views.
+ *
+ * Special "ignored views" are useful when dealing with things like nested
+ * frames within a page that periodically refresh themselves while the "main"
+ * part of the page remains unsubmitted.
+ */
+ public void setIgnoreViewIds(Set ignoreViewIds)
+ {
+ this.ignoreViewIds = ignoreViewIds;
+ }
}
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=629975&r1=629974&r2=629975&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 Thu Feb 21 12:32:37 2008
@@ -57,399 +57,399 @@
*/
public class Conversation
{
- // See getCurrentInstance, setCurrentInstance and class CurrentConversationAdvice.
- private final static ThreadLocal CURRENT_CONVERSATION = new ThreadLocal();
+ // See getCurrentInstance, setCurrentInstance and class CurrentConversationAdvice.
+ private final static ThreadLocal CURRENT_CONVERSATION = new ThreadLocal();
- private final Log log = LogFactory.getLog(Conversation.class);
+ private final Log log = LogFactory.getLog(Conversation.class);
- private final String name;
-
- // The factory that created this conversation instance; needed
- // when restarting the conversation.
- private final ConversationFactory factory;
-
- // The set of managed beans that are associated with this conversation.
- private final Map beans = new TreeMap();
-
- // The parent context to which this conversation belongs. This is needed
- // when restarting the conversation.
- private final ConversationContext conversationContext;
-
- // See addAspect.
- private ConversationAspects conversationAspects = new ConversationAspects();
-
- // Is this object usable, or "destroyed"?
- private boolean invalid = false;
-
- // Is this object going to be destroyed as soon as it is no longer "active"?
- private boolean queueInvalid = false;
-
- // system timestamp in milliseconds at which this object was last accessed;
- // see method touch().
- private long lastAccess;
-
- private Object activeCountMutex = new Object();
- private int activeCount;
-
- public Conversation(ConversationContext conversationContext, String name, ConversationFactory factory)
- {
- this.conversationContext = conversationContext;
- this.name = name;
- this.factory = factory;
-
- if (log.isDebugEnabled())
- {
- log.debug("start conversation:" + name);
- }
-
- touch();
- }
-
- /**
- * Mark this conversation as having been used at the current time.
- * <p>
- * Conversations can have "timeouts" associated with them, so that when a user stops
- * a conversation and goes off to work on some other part of the webapp then the
- * conversation's memory can eventually be reclaimed.
- * <p>
- * Whenever user code causes this conversation object to be looked up and returned,
- * this "touch" method is invoked to indicate that the conversation is in use. Direct
- * conversation lookups by user code can occur, but the most common access is expected
- * to be via an EL expression which a lookup of a bean that is declared as being in
- * conversation scope. The bean lookup causes the corresponding conversation to be
- * looked up, which triggers this method.
- */
- protected void touch()
- {
- lastAccess = System.currentTimeMillis();
- }
-
- /**
- * The system time in millis when this conversation has been accessed last
- */
- public long getLastAccess()
- {
- return lastAccess;
- }
-
- /**
- * Add the given bean to the conversation scope.
- *
- * <p>This will fire a {@link ConversationBindingEvent} on the bean parameter
- * object if the bean implements the {@link ConversationBindingListener}
- * interface</p>
- *
- * <p>Note that any object can be stored into the conversation; it is not
- * limited to managed beans declared in a configuration file. This
- * feature is not expected to be heavily used however; most attributes of
- * a conversation are expected to be externally-declared "managed beans".</p>
- */
- public void setAttribute(String name, Object bean)
- {
- checkValid();
-
- synchronized(conversationContext)
- {
- removeAttribute(name);
-
- if (log.isDebugEnabled())
- {
- log.debug("put bean to conversation:" + name + "(bean=" + bean + ")");
- }
-
- beans.put(name, bean);
- }
-
- if (bean instanceof ConversationBindingListener)
- {
- ((ConversationBindingListener) bean).valueBound(
- new ConversationBindingEvent(this, name));
- }
- }
-
- /**
- * Assert the conversation is valid.
- *
- * Throws IllegalStateException if this conversation has been destroyed;
- * see method setInvalid.
- */
- protected void checkValid()
- {
- if (isInvalid())
- {
- throw new IllegalStateException("conversation '" + getName() + "' closed");
- }
- }
-
- /**
- * Return the name of this conversation.
- * <p>
- * A conversation name is unique within a conversation context.
- */
- public String getName()
- {
- return name;
- }
-
- /**
- * Return the factory that created this conversation.
- * <p>
- * Note that this factory will have set the initial aspects of this factory, which
- * configure such things as the lifetime (access, manual, etc) and conversation
- * timeout properties.
- */
- public ConversationFactory getFactory()
- {
- return factory;
- }
-
- /**
- * Invalidate (end) the conversation.
- * <p>
- * If the conversation is currently active (ie the current call stack contains an object that
- * belongs to this conversation) then the conversation will just queue the object for later
- * destruction. Calls to methods like ConversationManager.getConversation(...) may still
- * return this object, and it will continue to function as a normal instance.
- * <p>
- * Only when the conversation is no longer active will the conversation (and the beans
- * it contains) actually be marked as invalid ("destroyed"). Once the conversation has been
- * destroyed, the ConversationManager will discard all references to it, meaning it will no
- * longer be accessable via lookups like ConversationManager.getConversation(). If something
- * does still have a reference to a destroyed conversation, then invoking almost any method
- * on that object will throw an IllegalStateException. In particular, adding a bean to the
- * conversation (invoking addAttribute) is not allowed.
- */
- public void invalidate()
- {
- if (!isActive())
- {
- destroy();
- }
- else
- {
- queueInvalid = true;
-
- if (log.isDebugEnabled())
- {
- log.debug("conversation '" + name + "' queued for destroy.");
- }
- }
- }
-
- /**
- * Invalidate/End and restart the conversation.
- * <p>
- * This conversation object is immediately "destroyed" (see comments for method
- * invalidate), and a new instance is registered with the conversation manager
- * using the same name. The new instance is returned from this method.
- * <p>
- * Any code holding a reference to the old conversation instance will receive
- * an IllegalStateException when calling almost any method on that instance.
- *
- * @returns the new conversation
- */
- public Conversation invalidateAndRestart()
- {
- String conversationName = getName();
- ConversationFactory factory = getFactory();
-
- destroy();
-
- return conversationContext.startConversation(conversationName, factory);
- }
-
- /**
- * Return true if the conversation is invalid, ie should not be used.
- */
- public boolean isInvalid()
- {
- return invalid;
- }
-
- /**
- * Return true if the conversation has been queued to be invalidated.
- */
- boolean isQueueInvalid()
- {
- return queueInvalid;
- }
-
- /**
- * Destroy the conversation.
- * <ul>
- * <li>inform all beans implementing the {@link ConversationBindingListener} about the conversation end</li>
- * <li>free all beans</li>
- * </ul>
- */
- protected void destroy()
- {
- if (log.isDebugEnabled())
- {
- log.debug("destroy conversation:" + name);
- }
-
- synchronized(conversationContext)
- {
- String[] beanNames = (String[]) beans.keySet().toArray(new String[beans.size()]);
- for (int i = 0; i< beanNames.length; i++)
- {
- removeAttribute(beanNames[i]);
- }
- }
-
- conversationContext.removeConversation(getName());
-
- invalid = true;
- }
-
- /**
- * Check if this conversation holds a specific attribute (ie has a specific
- * named managed bean instance).
- */
- public boolean hasAttribute(String name)
- {
- synchronized(conversationContext)
- {
- return beans.containsKey(name);
- }
- }
-
- /**
- * Get a specific attribute, ie a named managed bean.
- */
- public Object getAttribute(String name)
- {
- synchronized(conversationContext)
- {
- return beans.get(name);
- }
- }
-
- /**
- * Remove a bean from the conversation.
- *
- * <p>This will fire a {@link ConversationBindingEvent} if the bean implements the
- * {@link ConversationBindingListener} interface.</p>
- */
- public Object removeAttribute(String name)
- {
- synchronized(conversationContext)
- {
- Object bean = beans.remove(name);
- if (bean instanceof ConversationBindingListener)
- {
- ((ConversationBindingListener) bean).valueUnbound(
- new ConversationBindingEvent(this, name));
- }
- return bean;
- }
- }
-
- /**
- * Get the current conversation.
- *
- * @return The conversation object associated with the nearest object in the call-stack that
- * is configured to be in a conversation. Null is returned when no object in the call-stack
- * is in a conversation.
- */
- public static Conversation getCurrentInstance()
- {
- CurrentConversationInfo conversation = getCurrentInstanceInfo();
- if (conversation != null)
- {
- return conversation.getConversation();
- }
-
- return null;
- }
-
- /**
- * Sets info about the current conversation instance.
- * <p>
- * This method is only expected to be called by CurrentConversationAdvice.invoke,
- * which ensures that the current instance is reset to null as soon as no bean
- * in the call-stack is within a conversation.
- */
- static void setCurrentInstance(CurrentConversationInfo conversation)
- {
- CURRENT_CONVERSATION.set(conversation);
- }
-
- /**
- * Returns the info about the current conversation
- */
- static CurrentConversationInfo getCurrentInstanceInfo()
- {
- CurrentConversationInfo conversationInfo = (CurrentConversationInfo) CURRENT_CONVERSATION.get();
- if (conversationInfo != null && conversationInfo.getConversation() != null)
- {
- conversationInfo.getConversation().touch();
- return conversationInfo;
- }
-
- return null;
- }
-
- /**
- * Increase one to the "conversation active" counter.
- *
- * This is called when a method is invoked on a bean that is within this conversation.
- * When the method returns, leaveConversation is invoked. The result is that the count
- * is greater than zero whenever there is a bean belonging to this conversation on
- * the callstack.
- */
- void enterConversation()
- {
- synchronized (activeCountMutex)
- {
- activeCount++;
- }
- }
-
- /**
- * decrease one from the "conversation active" counter
- */
- void leaveConversation()
- {
- synchronized (activeCountMutex)
- {
- activeCount--;
- }
- }
-
- /**
- * check if the conversation is active
- */
- private boolean isActive()
- {
- synchronized (activeCountMutex)
- {
- return activeCount > 0;
- }
- }
-
- ConversationAspects getAspects()
- {
- return conversationAspects;
- }
-
- /**
- * Get the aspect corresponding to the given class.
- *
- * @return null if such an aspect has not been attached to this conversation
- */
- public ConversationAspect getAspect(Class conversationAspectClass)
- {
- return conversationAspects.getAspect(conversationAspectClass);
- }
-
- /**
- * Add an Aspect to this conversation.
- *
- * See class ConversationAspects for further details.
- */
- public void addAspect(ConversationAspect aspect)
- {
- conversationAspects.addAspect(aspect);
- }
+ private final String name;
+
+ // The factory that created this conversation instance; needed
+ // when restarting the conversation.
+ private final ConversationFactory factory;
+
+ // The set of managed beans that are associated with this conversation.
+ private final Map beans = new TreeMap();
+
+ // The parent context to which this conversation belongs. This is needed
+ // when restarting the conversation.
+ private final ConversationContext conversationContext;
+
+ // See addAspect.
+ private ConversationAspects conversationAspects = new ConversationAspects();
+
+ // Is this object usable, or "destroyed"?
+ private boolean invalid = false;
+
+ // Is this object going to be destroyed as soon as it is no longer "active"?
+ private boolean queueInvalid = false;
+
+ // system timestamp in milliseconds at which this object was last accessed;
+ // see method touch().
+ private long lastAccess;
+
+ private Object activeCountMutex = new Object();
+ private int activeCount;
+
+ public Conversation(ConversationContext conversationContext, String name, ConversationFactory factory)
+ {
+ this.conversationContext = conversationContext;
+ this.name = name;
+ this.factory = factory;
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("start conversation:" + name);
+ }
+
+ touch();
+ }
+
+ /**
+ * Mark this conversation as having been used at the current time.
+ * <p>
+ * Conversations can have "timeouts" associated with them, so that when a user stops
+ * a conversation and goes off to work on some other part of the webapp then the
+ * conversation's memory can eventually be reclaimed.
+ * <p>
+ * Whenever user code causes this conversation object to be looked up and returned,
+ * this "touch" method is invoked to indicate that the conversation is in use. Direct
+ * conversation lookups by user code can occur, but the most common access is expected
+ * to be via an EL expression which a lookup of a bean that is declared as being in
+ * conversation scope. The bean lookup causes the corresponding conversation to be
+ * looked up, which triggers this method.
+ */
+ protected void touch()
+ {
+ lastAccess = System.currentTimeMillis();
+ }
+
+ /**
+ * The system time in millis when this conversation has been accessed last
+ */
+ public long getLastAccess()
+ {
+ return lastAccess;
+ }
+
+ /**
+ * Add the given bean to the conversation scope.
+ *
+ * <p>This will fire a {@link ConversationBindingEvent} on the bean parameter
+ * object if the bean implements the {@link ConversationBindingListener}
+ * interface</p>
+ *
+ * <p>Note that any object can be stored into the conversation; it is not
+ * limited to managed beans declared in a configuration file. This
+ * feature is not expected to be heavily used however; most attributes of
+ * a conversation are expected to be externally-declared "managed beans".</p>
+ */
+ public void setAttribute(String name, Object bean)
+ {
+ checkValid();
+
+ synchronized(conversationContext)
+ {
+ removeAttribute(name);
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("put bean to conversation:" + name + "(bean=" + bean + ")");
+ }
+
+ beans.put(name, bean);
+ }
+
+ if (bean instanceof ConversationBindingListener)
+ {
+ ((ConversationBindingListener) bean).valueBound(
+ new ConversationBindingEvent(this, name));
+ }
+ }
+
+ /**
+ * Assert the conversation is valid.
+ *
+ * Throws IllegalStateException if this conversation has been destroyed;
+ * see method setInvalid.
+ */
+ protected void checkValid()
+ {
+ if (isInvalid())
+ {
+ throw new IllegalStateException("conversation '" + getName() + "' closed");
+ }
+ }
+
+ /**
+ * Return the name of this conversation.
+ * <p>
+ * A conversation name is unique within a conversation context.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Return the factory that created this conversation.
+ * <p>
+ * Note that this factory will have set the initial aspects of this factory, which
+ * configure such things as the lifetime (access, manual, etc) and conversation
+ * timeout properties.
+ */
+ public ConversationFactory getFactory()
+ {
+ return factory;
+ }
+
+ /**
+ * Invalidate (end) the conversation.
+ * <p>
+ * If the conversation is currently active (ie the current call stack contains an object that
+ * belongs to this conversation) then the conversation will just queue the object for later
+ * destruction. Calls to methods like ConversationManager.getConversation(...) may still
+ * return this object, and it will continue to function as a normal instance.
+ * <p>
+ * Only when the conversation is no longer active will the conversation (and the beans
+ * it contains) actually be marked as invalid ("destroyed"). Once the conversation has been
+ * destroyed, the ConversationManager will discard all references to it, meaning it will no
+ * longer be accessable via lookups like ConversationManager.getConversation(). If something
+ * does still have a reference to a destroyed conversation, then invoking almost any method
+ * on that object will throw an IllegalStateException. In particular, adding a bean to the
+ * conversation (invoking addAttribute) is not allowed.
+ */
+ public void invalidate()
+ {
+ if (!isActive())
+ {
+ destroy();
+ }
+ else
+ {
+ queueInvalid = true;
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("conversation '" + name + "' queued for destroy.");
+ }
+ }
+ }
+
+ /**
+ * Invalidate/End and restart the conversation.
+ * <p>
+ * This conversation object is immediately "destroyed" (see comments for method
+ * invalidate), and a new instance is registered with the conversation manager
+ * using the same name. The new instance is returned from this method.
+ * <p>
+ * Any code holding a reference to the old conversation instance will receive
+ * an IllegalStateException when calling almost any method on that instance.
+ *
+ * @returns the new conversation
+ */
+ public Conversation invalidateAndRestart()
+ {
+ String conversationName = getName();
+ ConversationFactory factory = getFactory();
+
+ destroy();
+
+ return conversationContext.startConversation(conversationName, factory);
+ }
+
+ /**
+ * Return true if the conversation is invalid, ie should not be used.
+ */
+ public boolean isInvalid()
+ {
+ return invalid;
+ }
+
+ /**
+ * Return true if the conversation has been queued to be invalidated.
+ */
+ boolean isQueueInvalid()
+ {
+ return queueInvalid;
+ }
+
+ /**
+ * Destroy the conversation.
+ * <ul>
+ * <li>inform all beans implementing the {@link ConversationBindingListener} about the conversation end</li>
+ * <li>free all beans</li>
+ * </ul>
+ */
+ protected void destroy()
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("destroy conversation:" + name);
+ }
+
+ synchronized(conversationContext)
+ {
+ String[] beanNames = (String[]) beans.keySet().toArray(new String[beans.size()]);
+ for (int i = 0; i< beanNames.length; i++)
+ {
+ removeAttribute(beanNames[i]);
+ }
+ }
+
+ conversationContext.removeConversation(getName());
+
+ invalid = true;
+ }
+
+ /**
+ * Check if this conversation holds a specific attribute (ie has a specific
+ * named managed bean instance).
+ */
+ public boolean hasAttribute(String name)
+ {
+ synchronized(conversationContext)
+ {
+ return beans.containsKey(name);
+ }
+ }
+
+ /**
+ * Get a specific attribute, ie a named managed bean.
+ */
+ public Object getAttribute(String name)
+ {
+ synchronized(conversationContext)
+ {
+ return beans.get(name);
+ }
+ }
+
+ /**
+ * Remove a bean from the conversation.
+ *
+ * <p>This will fire a {@link ConversationBindingEvent} if the bean implements the
+ * {@link ConversationBindingListener} interface.</p>
+ */
+ public Object removeAttribute(String name)
+ {
+ synchronized(conversationContext)
+ {
+ Object bean = beans.remove(name);
+ if (bean instanceof ConversationBindingListener)
+ {
+ ((ConversationBindingListener) bean).valueUnbound(
+ new ConversationBindingEvent(this, name));
+ }
+ return bean;
+ }
+ }
+
+ /**
+ * Get the current conversation.
+ *
+ * @return The conversation object associated with the nearest object in the call-stack that
+ * is configured to be in a conversation. Null is returned when no object in the call-stack
+ * is in a conversation.
+ */
+ public static Conversation getCurrentInstance()
+ {
+ CurrentConversationInfo conversation = getCurrentInstanceInfo();
+ if (conversation != null)
+ {
+ return conversation.getConversation();
+ }
+
+ return null;
+ }
+
+ /**
+ * Sets info about the current conversation instance.
+ * <p>
+ * This method is only expected to be called by CurrentConversationAdvice.invoke,
+ * which ensures that the current instance is reset to null as soon as no bean
+ * in the call-stack is within a conversation.
+ */
+ static void setCurrentInstance(CurrentConversationInfo conversation)
+ {
+ CURRENT_CONVERSATION.set(conversation);
+ }
+
+ /**
+ * Returns the info about the current conversation
+ */
+ static CurrentConversationInfo getCurrentInstanceInfo()
+ {
+ CurrentConversationInfo conversationInfo = (CurrentConversationInfo) CURRENT_CONVERSATION.get();
+ if (conversationInfo != null && conversationInfo.getConversation() != null)
+ {
+ conversationInfo.getConversation().touch();
+ return conversationInfo;
+ }
+
+ return null;
+ }
+
+ /**
+ * Increase one to the "conversation active" counter.
+ *
+ * This is called when a method is invoked on a bean that is within this conversation.
+ * When the method returns, leaveConversation is invoked. The result is that the count
+ * is greater than zero whenever there is a bean belonging to this conversation on
+ * the callstack.
+ */
+ void enterConversation()
+ {
+ synchronized (activeCountMutex)
+ {
+ activeCount++;
+ }
+ }
+
+ /**
+ * decrease one from the "conversation active" counter
+ */
+ void leaveConversation()
+ {
+ synchronized (activeCountMutex)
+ {
+ activeCount--;
+ }
+ }
+
+ /**
+ * check if the conversation is active
+ */
+ private boolean isActive()
+ {
+ synchronized (activeCountMutex)
+ {
+ return activeCount > 0;
+ }
+ }
+
+ ConversationAspects getAspects()
+ {
+ return conversationAspects;
+ }
+
+ /**
+ * Get the aspect corresponding to the given class.
+ *
+ * @return null if such an aspect has not been attached to this conversation
+ */
+ public ConversationAspect getAspect(Class conversationAspectClass)
+ {
+ return conversationAspects.getAspect(conversationAspectClass);
+ }
+
+ /**
+ * Add an Aspect to this conversation.
+ *
+ * See class ConversationAspects for further details.
+ */
+ public void addAspect(ConversationAspect aspect)
+ {
+ conversationAspects.addAspect(aspect);
+ }
}
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAccessLifetimeAspect.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAccessLifetimeAspect.java?rev=629975&r1=629974&r2=629975&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAccessLifetimeAspect.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAccessLifetimeAspect.java Thu Feb 21 12:32:37 2008
@@ -25,18 +25,18 @@
*/
public class ConversationAccessLifetimeAspect extends ConversationAspect
{
- public ConversationAccessLifetimeAspect(Conversation conversation)
- {
- super(conversation);
- }
+ public ConversationAccessLifetimeAspect(Conversation conversation)
+ {
+ super(conversation);
+ }
- public void markAsAccessed()
- {
- AccessScopeManager.getInstance().addConversationAccess(getConversation().getName());
- }
+ public void markAsAccessed()
+ {
+ AccessScopeManager.getInstance().addConversationAccess(getConversation().getName());
+ }
- public boolean isAccessed()
- {
- return AccessScopeManager.getInstance().isConversationAccessed(getConversation().getName());
- }
+ public boolean isAccessed()
+ {
+ return AccessScopeManager.getInstance().isConversationAccessed(getConversation().getName());
+ }
}
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java?rev=629975&r1=629974&r2=629975&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java Thu Feb 21 12:32:37 2008
@@ -25,15 +25,15 @@
*/
public abstract class ConversationAspect
{
- private final Conversation conversation;
+ private final Conversation conversation;
- public ConversationAspect(Conversation conversation)
- {
- this.conversation = conversation;
- }
+ public ConversationAspect(Conversation conversation)
+ {
+ this.conversation = conversation;
+ }
- public Conversation getConversation()
- {
- return conversation;
- }
+ public Conversation getConversation()
+ {
+ return conversation;
+ }
}
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java?rev=629975&r1=629974&r2=629975&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java Thu Feb 21 12:32:37 2008
@@ -45,15 +45,15 @@
*/
public class ConversationAspects
{
- private Map conversationAspects = new HashMap();
+ private Map conversationAspects = new HashMap();
- public void addAspect(ConversationAspect aspect)
- {
- conversationAspects.put(aspect.getClass().getName(), aspect);
- }
+ public void addAspect(ConversationAspect aspect)
+ {
+ conversationAspects.put(aspect.getClass().getName(), aspect);
+ }
- public ConversationAspect getAspect(Class aspectClass)
- {
- return (ConversationAspect) conversationAspects.get(aspectClass.getName());
- }
+ public ConversationAspect getAspect(Class aspectClass)
+ {
+ return (ConversationAspect) conversationAspects.get(aspectClass.getName());
+ }
}
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAware.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAware.java?rev=629975&r1=629974&r2=629975&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAware.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAware.java Thu Feb 21 12:32:37 2008
@@ -30,8 +30,8 @@
*/
public interface ConversationAware
{
- /**
- * The conversation the bean implementing this interface belongs to.
- */
- public void setConversation(Conversation conversation);
+ /**
+ * The conversation the bean implementing this interface belongs to.
+ */
+ public void setConversation(Conversation conversation);
}
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationBindingEvent.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationBindingEvent.java?rev=629975&r1=629974&r2=629975&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationBindingEvent.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationBindingEvent.java Thu Feb 21 12:32:37 2008
@@ -25,22 +25,22 @@
*/
public class ConversationBindingEvent
{
- private final Conversation conversation;
- private final String name;
+ private final Conversation conversation;
+ private final String name;
- protected ConversationBindingEvent(Conversation conversation, String name)
- {
- this.conversation = conversation;
- this.name = name;
- }
+ protected ConversationBindingEvent(Conversation conversation, String name)
+ {
+ this.conversation = conversation;
+ this.name = name;
+ }
- public Conversation getConversation()
- {
- return conversation;
- }
+ public Conversation getConversation()
+ {
+ return conversation;
+ }
- public String getName()
- {
- return name;
- }
+ public String getName()
+ {
+ return name;
+ }
}
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationBindingListener.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationBindingListener.java?rev=629975&r1=629974&r2=629975&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationBindingListener.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationBindingListener.java Thu Feb 21 12:32:37 2008
@@ -28,13 +28,13 @@
*/
public interface ConversationBindingListener
{
- /**
- * The bean has been added to the conversation.
- */
- public void valueBound(ConversationBindingEvent event);
+ /**
+ * The bean has been added to the conversation.
+ */
+ public void valueBound(ConversationBindingEvent event);
- /**
- * The bean has been removed from the conversation.
- */
- public void valueUnbound(ConversationBindingEvent event);
+ /**
+ * The bean has been removed from the conversation.
+ */
+ public void valueUnbound(ConversationBindingEvent event);
}
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=629975&r1=629974&r2=629975&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 Thu Feb 21 12:32:37 2008
@@ -40,325 +40,325 @@
*/
public class ConversationContext
{
- private final Log log = LogFactory.getLog(ConversationContext.class);
+ private final Log log = LogFactory.getLog(ConversationContext.class);
- // 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;
-
- // See addAttribute
- private final Map attributes = new TreeMap();
-
- // The conversations held by this context, keyed by conversation name.
- private final Map conversations = new TreeMap();
-
- // 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)
- {
- this.id = id;
-
- touch();
- }
-
- /**
- * The conversation context id, unique within the current http session.
- */
- public long getId()
- {
- return id;
- }
-
- /**
- * Mark this context as having been used.
- */
- protected void touch()
- {
- lastAccess = System.currentTimeMillis();
- }
-
- /**
- * The system time in millis when this conversation has been accessed last.
- */
- public long getLastAccess()
- {
- return lastAccess;
- }
-
- /**
- * Get the timeout after which this context will be closed.
- *
- * @see #setTimeout
- */
- public long getTimeout()
- {
- return timeoutMillis;
- }
-
- /**
- * Set the timeout after which this context will be closed.
- * <p>
- * A value of -1 means no timeout checking.
- */
- public void setTimeout(long timeoutMillis)
- {
- this.timeoutMillis = timeoutMillis;
- }
-
- /**
- * Invalidate all conversations within this context.
- */
- protected void clear()
- {
- synchronized (this)
- {
- Conversation[] convArray = new Conversation[conversations.size()];
- conversations.values().toArray(convArray);
-
- for (int i = 0; i < convArray.length; i++)
- {
- Conversation conversation = convArray[i];
- conversation.invalidate();
- }
-
- conversations.clear();
- }
- }
-
- /**
- * Start a conversation if not already started.
- */
- protected Conversation startConversation(String name, ConversationFactory factory)
- {
- synchronized (this)
- {
- touch();
- Conversation conversation = (Conversation) conversations.get(name);
- if (conversation == null)
- {
- conversation = factory.createConversation(this, name);
-
- conversations.put(name, conversation);
- }
- return conversation;
- }
- }
-
- /**
- * Remove the conversation from this context.
- *
- * <p>Notice: It is assumed that the conversation has already been invalidated.</p>
- */
- protected void removeConversation(Conversation conversation)
- {
- synchronized (this)
- {
- touch();
- conversations.remove(conversation.getName());
- }
- }
-
- /**
- * 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)
- {
- synchronized (this)
- {
- touch();
- Conversation conversation = (Conversation) conversations.get(name);
- if (conversation != null)
- {
- removeConversation(conversation);
- }
- }
- }
-
- /**
- * See if there is a conversation with the specified name.
- */
- protected boolean hasConversations()
- {
- synchronized (this)
- {
- touch();
- return conversations.size() > 0;
- }
- }
-
- /**
- * Check if the given conversation exists.
- */
- protected boolean hasConversation(String name)
- {
- synchronized (this)
- {
- touch();
- return conversations.get(name) != null;
- }
- }
-
- /**
- * Get a conversation by name.
- */
- protected Conversation getConversation(String name)
- {
- synchronized (this)
- {
- touch();
-
- Conversation conv = (Conversation) conversations.get(name);
- if (conv != null)
- {
- conv.touch();
- }
-
- return conv;
- }
- }
-
- /**
- * Iterates over all the conversations in this context.
- *
- * @return An iterator over a copy of the conversation list. It is safe to remove objects from
- * the conversation list while iterating, as the iterator refers to a different collection.
- */
- public Iterator iterateConversations()
- {
- synchronized (this)
- {
- touch();
-
- Conversation[] convs = (Conversation[]) conversations.values().toArray(new Conversation[conversations.size()]);
- return Arrays.asList(convs).iterator();
- }
- }
-
- /**
- * Check the timeout for every conversation in this context.
- * <p>
- * This method does not check the timeout for this context object itself.
- */
- protected void checkConversationTimeout()
- {
- synchronized (this)
- {
- Conversation[] convArray = new Conversation[conversations.size()];
- conversations.values().toArray(convArray);
-
- for (int i = 0; i < convArray.length; i++)
- {
- Conversation conversation = convArray[i];
-
- ConversationTimeoutableAspect timeoutAspect =
- (ConversationTimeoutableAspect)
- conversation.getAspect(ConversationTimeoutableAspect.class);
-
- if (timeoutAspect != null && timeoutAspect.isTimeoutReached())
- {
- if (log.isDebugEnabled())
- {
- log.debug("end conversation due to timeout: " + conversation.getName());
- }
-
- conversation.invalidate();
- }
- }
- }
- }
-
- /**
- * Add an attribute to the conversationContext.
- * <p>
- * A context provides a map into which any arbitrary objects can be stored. It
- * isn't a major feature of the context, but can occasionally be useful.
- */
- public void setAttribute(String name, Object attribute)
- {
- synchronized(attributes)
- {
- attributes.remove(name);
- attributes.put(name, attribute);
- }
- }
-
- /**
- * Check if this conversationContext holds a specific attribute.
- */
- public boolean hasAttribute(String name)
- {
- synchronized(attributes)
- {
- return attributes.containsKey(name);
- }
- }
-
- /**
- * Get a specific attribute.
- */
- public Object getAttribute(String name)
- {
- synchronized(attributes)
- {
- return attributes.get(name);
- }
- }
-
- /**
- * Remove an attribute from the conversationContext.
- */
- public Object removeAttribute(String name)
- {
- synchronized(attributes)
- {
- return attributes.remove(name);
- }
- }
-
- /**
- * Block until no other thread has this instance marked as reserved, then
- * mark the object as reserved for this thread.
- * <p>
- * It is safe to call this method multiple times.
- * <p>
- * 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.
- *
- * @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();
- }
-}
\ No newline at end of file
+ // 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;
+
+ // See addAttribute
+ private final Map attributes = new TreeMap();
+
+ // The conversations held by this context, keyed by conversation name.
+ private final Map conversations = new TreeMap();
+
+ // 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)
+ {
+ this.id = id;
+
+ touch();
+ }
+
+ /**
+ * The conversation context id, unique within the current http session.
+ */
+ public long getId()
+ {
+ return id;
+ }
+
+ /**
+ * Mark this context as having been used.
+ */
+ protected void touch()
+ {
+ lastAccess = System.currentTimeMillis();
+ }
+
+ /**
+ * The system time in millis when this conversation has been accessed last.
+ */
+ public long getLastAccess()
+ {
+ return lastAccess;
+ }
+
+ /**
+ * Get the timeout after which this context will be closed.
+ *
+ * @see #setTimeout
+ */
+ public long getTimeout()
+ {
+ return timeoutMillis;
+ }
+
+ /**
+ * Set the timeout after which this context will be closed.
+ * <p>
+ * A value of -1 means no timeout checking.
+ */
+ public void setTimeout(long timeoutMillis)
+ {
+ this.timeoutMillis = timeoutMillis;
+ }
+
+ /**
+ * Invalidate all conversations within this context.
+ */
+ protected void clear()
+ {
+ synchronized (this)
+ {
+ Conversation[] convArray = new Conversation[conversations.size()];
+ conversations.values().toArray(convArray);
+
+ for (int i = 0; i < convArray.length; i++)
+ {
+ Conversation conversation = convArray[i];
+ conversation.invalidate();
+ }
+
+ conversations.clear();
+ }
+ }
+
+ /**
+ * Start a conversation if not already started.
+ */
+ protected Conversation startConversation(String name, ConversationFactory factory)
+ {
+ synchronized (this)
+ {
+ touch();
+ Conversation conversation = (Conversation) conversations.get(name);
+ if (conversation == null)
+ {
+ conversation = factory.createConversation(this, name);
+
+ conversations.put(name, conversation);
+ }
+ return conversation;
+ }
+ }
+
+ /**
+ * Remove the conversation from this context.
+ *
+ * <p>Notice: It is assumed that the conversation has already been invalidated.</p>
+ */
+ protected void removeConversation(Conversation conversation)
+ {
+ synchronized (this)
+ {
+ touch();
+ conversations.remove(conversation.getName());
+ }
+ }
+
+ /**
+ * 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)
+ {
+ synchronized (this)
+ {
+ touch();
+ Conversation conversation = (Conversation) conversations.get(name);
+ if (conversation != null)
+ {
+ removeConversation(conversation);
+ }
+ }
+ }
+
+ /**
+ * See if there is a conversation with the specified name.
+ */
+ protected boolean hasConversations()
+ {
+ synchronized (this)
+ {
+ touch();
+ return conversations.size() > 0;
+ }
+ }
+
+ /**
+ * Check if the given conversation exists.
+ */
+ protected boolean hasConversation(String name)
+ {
+ synchronized (this)
+ {
+ touch();
+ return conversations.get(name) != null;
+ }
+ }
+
+ /**
+ * Get a conversation by name.
+ */
+ protected Conversation getConversation(String name)
+ {
+ synchronized (this)
+ {
+ touch();
+
+ Conversation conv = (Conversation) conversations.get(name);
+ if (conv != null)
+ {
+ conv.touch();
+ }
+
+ return conv;
+ }
+ }
+
+ /**
+ * Iterates over all the conversations in this context.
+ *
+ * @return An iterator over a copy of the conversation list. It is safe to remove objects from
+ * the conversation list while iterating, as the iterator refers to a different collection.
+ */
+ public Iterator iterateConversations()
+ {
+ synchronized (this)
+ {
+ touch();
+
+ Conversation[] convs = (Conversation[]) conversations.values().toArray(new Conversation[conversations.size()]);
+ return Arrays.asList(convs).iterator();
+ }
+ }
+
+ /**
+ * Check the timeout for every conversation in this context.
+ * <p>
+ * This method does not check the timeout for this context object itself.
+ */
+ protected void checkConversationTimeout()
+ {
+ synchronized (this)
+ {
+ Conversation[] convArray = new Conversation[conversations.size()];
+ conversations.values().toArray(convArray);
+
+ for (int i = 0; i < convArray.length; i++)
+ {
+ Conversation conversation = convArray[i];
+
+ ConversationTimeoutableAspect timeoutAspect =
+ (ConversationTimeoutableAspect)
+ conversation.getAspect(ConversationTimeoutableAspect.class);
+
+ if (timeoutAspect != null && timeoutAspect.isTimeoutReached())
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("end conversation due to timeout: " + conversation.getName());
+ }
+
+ conversation.invalidate();
+ }
+ }
+ }
+ }
+
+ /**
+ * Add an attribute to the conversationContext.
+ * <p>
+ * A context provides a map into which any arbitrary objects can be stored. It
+ * isn't a major feature of the context, but can occasionally be useful.
+ */
+ public void setAttribute(String name, Object attribute)
+ {
+ synchronized(attributes)
+ {
+ attributes.remove(name);
+ attributes.put(name, attribute);
+ }
+ }
+
+ /**
+ * Check if this conversationContext holds a specific attribute.
+ */
+ public boolean hasAttribute(String name)
+ {
+ synchronized(attributes)
+ {
+ return attributes.containsKey(name);
+ }
+ }
+
+ /**
+ * Get a specific attribute.
+ */
+ public Object getAttribute(String name)
+ {
+ synchronized(attributes)
+ {
+ return attributes.get(name);
+ }
+ }
+
+ /**
+ * Remove an attribute from the conversationContext.
+ */
+ public Object removeAttribute(String name)
+ {
+ synchronized(attributes)
+ {
+ return attributes.remove(name);
+ }
+ }
+
+ /**
+ * Block until no other thread has this instance marked as reserved, then
+ * mark the object as reserved for this thread.
+ * <p>
+ * It is safe to call this method multiple times.
+ * <p>
+ * 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.
+ *
+ * @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();
+ }
+}
Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFactory.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFactory.java?rev=629975&r1=629974&r2=629975&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFactory.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFactory.java Thu Feb 21 12:32:37 2008
@@ -26,5 +26,5 @@
*/
public interface ConversationFactory
{
- Conversation createConversation(ConversationContext context, String name);
-}
\ No newline at end of file
+ Conversation createConversation(ConversationContext context, String name);
+}