diff --git a/product/CMFActivity/ActiveObject.py b/product/CMFActivity/ActiveObject.py
index 5fbe5ed87c1cd041eaf30c196125f6f631477a2b..7c56deb15f4f68c2542c81f696d4839214f74855 100755
--- a/product/CMFActivity/ActiveObject.py
+++ b/product/CMFActivity/ActiveObject.py
@@ -29,6 +29,7 @@
 import ExtensionClass
 from AccessControl import ClassSecurityInfo
 from Products.CMFCore import CMFCorePermissions
+from Acquisition import aq_base
 
 from zLOG import LOG
 
@@ -37,27 +38,17 @@ DEFAULT_ACTIVITY = 'SQLDict'
 #DEFAULT_ACTIVITY = 'RAMDict'
 
 
-def flushActivity(object, invoke=0, **kw):
-  # flush all activities related to this object
-  try:
-    object.portal_activities.flush(self, invoke=invoke, **kw)
-  except:
-    # If the portal_activities were not created
-    # nothing to do
-    pass
-
-
 class ActiveObject(ExtensionClass.Base):
 
   security = ClassSecurityInfo()
 
-  def activate(self, activity=DEFAULT_ACTIVITY, **kw):
+  def activate(self, activity=DEFAULT_ACTIVITY, active_process=None, **kw):
     # activate returns an ActiveWrapper
     # a queue can be provided as well as extra parameters
     # which can be used for example to define deferred tasks
     try:
     #if 1:
-      return self.portal_activities.activate(self,  activity, **kw)
+      return self.portal_activities.activate(self, activity, active_process, **kw)
     #else:
     except:
       LOG("WARNING CMFActivity:",0, 'could not create activity for %s' % self.getRelativeUrl())
@@ -65,6 +56,7 @@ class ActiveObject(ExtensionClass.Base):
       # return a passive object
       return self
 
+  security.declareProtected( CMFCorePermissions.ModifyPortalContent, 'hasActivity' )
   def flushActivity(self, invoke=0, **kw):
     # flush all activities related to this object
     #try:
@@ -75,10 +67,14 @@ class ActiveObject(ExtensionClass.Base):
     #  # nothing to do
     #  pass
 
-  def recursiveFlushActivity(self, **kw):
+  security.declareProtected( CMFCorePermissions.ModifyPortalContent, 'hasActivity' )
+  def recursiveFlushActivity(self, invoke=0, **kw):
     # flush all activities related to this object
-    # updateAll is defined in ERP5Type
-    self.recursiveApply(method=flushActivity, **kw)
+    self.flushActivity(invoke=invoke, **kw)
+    if hasattr(aq_base(self), 'objectValues'):
+      for o in self.objectValues():
+        if hasattr(aq_base(self), 'recursiveFlushActivity'):
+          o.recursiveFlushActivity(invoke=invoke, **kw)
 
   security.declareProtected( CMFCorePermissions.View, 'hasActivity' )
   def hasActivity(self, **kw):
@@ -91,3 +87,7 @@ class ActiveObject(ExtensionClass.Base):
       # If the portal_activities were not created
       # there can not be any activity
       return 0
+
+  security.declareProtected( CMFCorePermissions.View, 'hasActivity' )
+  def getActiveProcess(self):
+    return self.portal_activities.getActiveProcess()
diff --git a/product/CMFActivity/ActiveProcess.py b/product/CMFActivity/ActiveProcess.py
new file mode 100755
index 0000000000000000000000000000000000000000..aa22c322c77b211a2c2b581cb7202da9cbc6bda8
--- /dev/null
+++ b/product/CMFActivity/ActiveProcess.py
@@ -0,0 +1,106 @@
+##############################################################################
+#
+# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solane <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import aq_base
+from Globals import InitializeClass, DTMLFile
+from AccessControl import ClassSecurityInfo
+from Products.CMFCore import CMFCorePermissions
+from Products.ERP5Type.Base import Base
+from Products.ERP5Type import PropertySheet
+
+from zLOG import LOG
+
+manage_addActiveProcessForm=DTMLFile('dtml/ActiveProcess_add', globals())
+
+def addActiveProcess( self, id, title='', REQUEST=None ):
+    """
+        Add a new Category and generate UID by calling the
+        ZSQLCatalog
+    """
+    sf = ActiveProcess( id )
+    sf._setTitle(title)
+    self._setObject( id, sf )
+    sf = self._getOb( id )
+    sf.reindexObject()
+    if REQUEST is not None:
+        return self.manage_main(self, REQUEST, update_menu=1)
+
+class ActiveProcess(Base):
+    """
+        ActiveProcess is used to centralise interaction between multiple ActiveObject
+    """
+
+    meta_type='CMF Active Process'
+    portal_type=None # may be useful in the future...
+    isPortalContent = 0
+    isRADContent = 1
+    icon = None
+
+    # Declarative security
+    security = ClassSecurityInfo()
+    security.declareProtected(CMFCorePermissions.ManagePortal,
+                              'manage_editProperties',
+                              'manage_changeProperties',
+                              'manage_propertiesForm',
+                                )
+
+    # Declarative properties
+    property_sheets = ( PropertySheet.Base
+                      , PropertySheet.SimpleItem )
+
+    # Declarative constructors
+    constructors =   (manage_addActiveProcessForm, addActiveProcess)
+
+    # Base methods
+    security.declareProtected(CMFCorePermissions.ManagePortal, 'postError')
+    def postError(self, error):
+      if not hasattr(aq_base(self), 'error_list'):
+        self.error_list = []
+      self.error_list.append(error)
+
+    security.declareProtected(CMFCorePermissions.ManagePortal, 'getErrorList')
+    def getErrorList(self):
+      """
+        Returns the list of errors
+      """
+      return self.error_list
+
+    security.declareProtected(CMFCorePermissions.ManagePortal, 'getErrorListText')
+    def getErrorListText(self):
+      """
+        Returns the list of errors as text
+      """
+      return '\n'.join(self.error_list)
+
+    security.declareProtected(CMFCorePermissions.ManagePortal, 'activateResult')
+    def activateResult(self, result):
+      if result not in (None, 0, '', (), []):
+        self.activate().postError(result)
+
+
+InitializeClass( ActiveProcess )
diff --git a/product/CMFActivity/Activity/Queue.py b/product/CMFActivity/Activity/Queue.py
index 889593df25d5bdf7defb89aa9fd19c2d29c4e81b..e2918bff47bd688571045460706fbd3f53725c27 100755
--- a/product/CMFActivity/Activity/Queue.py
+++ b/product/CMFActivity/Activity/Queue.py
@@ -27,6 +27,7 @@
 ##############################################################################
 
 import pickle
+from Acquisition import aq_base
 from Products.CMFActivity.ActivityTool import Message
 from zLOG import LOG
 
diff --git a/product/CMFActivity/ActivityTool.py b/product/CMFActivity/ActivityTool.py
index d8e59ff168b6f7d5e99e803907abd9fec7f5cf92..ce16a5dc1a0a715f4ca99373cc6cfa6478825816 100755
--- a/product/CMFActivity/ActivityTool.py
+++ b/product/CMFActivity/ActivityTool.py
@@ -27,10 +27,10 @@
 ##############################################################################
 
 from Products.CMFCore import CMFCorePermissions
-from Products.CMFCore.PortalFolder import PortalFolder
+from Products.ERP5Type.Document.Folder import Folder
 from AccessControl import ClassSecurityInfo
 from Products.CMFCore.utils import UniqueObject, _checkPermission, _getAuthenticatedUser
-from Globals import InitializeClass, DTMLFile
+from Globals import InitializeClass, DTMLFile, get_request
 from Acquisition import aq_base
 from DateTime.DateTime import DateTime
 import threading
@@ -56,11 +56,17 @@ def registerActivity(activity):
   activity_dict[activity.__name__] = activity_instance
 
 class Message:
-  def __init__(self, object, activity_kw, method_id, args, kw):
+  def __init__(self, object, active_process, activity_kw, method_id, args, kw):
     if type(object) is type('a'):
       self.object_path = object.split('/')
     else:
       self.object_path = object.getPhysicalPath()
+    if type(active_process) is type('a'):
+      self.active_process = active_process.split('/')
+    elif active_process is None:
+      self.active_process = None
+    else:
+      self.active_process = active_process.getPhysicalPath()
     self.activity_kw = activity_kw
     self.method_id = method_id
     self.args = args
@@ -73,7 +79,12 @@ class Message:
       LOG('WARNING ActivityTool', 0,
            'Trying to call method %s on object %s' % (self.method_id, self.object_path))
       object = activity_tool.unrestrictedTraverse(self.object_path)
-      getattr(object, self.method_id)(*self.args, **self.kw)
+      REQUEST = get_request()
+      REQUEST.active_process = self.active_process
+      result = getattr(object, self.method_id)(*self.args, **self.kw)
+      if REQUEST.active_process is not None:
+        active_process = activity_tool.getActiveProcess()
+        active_process.activateResult(result) # XXX Allow other method_id in future
       self.__is_executed = 1
     except:
       LOG('WARNING ActivityTool', 0,
@@ -85,49 +96,69 @@ class Message:
 
 class Method:
 
-  def __init__(self, passive_self, activity, kw, method_id):
+  def __init__(self, passive_self, activity, active_process, kw, method_id):
     self.__passive_self = passive_self
     self.__activity = activity
+    self.__active_process = active_process
     self.__kw = kw
     self.__method_id = method_id
 
   def __call__(self, *args, **kw):
-    m = Message(self.__passive_self, self.__kw, self.__method_id, args, kw)
+    m = Message(self.__passive_self, self.__active_process, self.__kw, self.__method_id, args, kw)
     activity_dict[self.__activity].queueMessage(self.__passive_self.portal_activities, m)
 
 class ActiveWrapper:
 
-  def __init__(self, passive_self, activity, **kw):
+  def __init__(self, passive_self, activity, active_process, **kw):
     self.__dict__['__passive_self'] = passive_self
     self.__dict__['__activity'] = activity
+    self.__dict__['__active_process'] = active_process
     self.__dict__['__kw'] = kw
 
   def __getattr__(self, id):
     return Method(self.__dict__['__passive_self'], self.__dict__['__activity'],
+                  self.__dict__['__active_process'],
                   self.__dict__['__kw'], id)
 
-class ActivityTool (UniqueObject, PortalFolder):
+class ActivityTool (Folder, UniqueObject):
     """
     This is a ZSQLCatalog that filters catalog queries.
     It is based on ZSQLCatalog
     """
     id = 'portal_activities'
     meta_type = 'CMF Activity Tool'
+    allowed_types = ( 'CMF Active Process', )
     security = ClassSecurityInfo()
     tic_lock = threading.Lock()
 
-    manage_options = ( { 'label' : 'Overview', 'action' : 'manage_overview' }
+    manage_options = tuple(
+                     [ { 'label' : 'Overview', 'action' : 'manage_overview' }
                      , { 'label' : 'Activities', 'action' : 'manageActivities' }
                      ,
-                     )
-
+                     ] + list(Folder.manage_options))
 
     security.declareProtected( CMFCorePermissions.ManagePortal , 'manageActivities' )
     manageActivities = DTMLFile( 'dtml/manageActivities', globals() )
 
+    security.declareProtected( CMFCorePermissions.ManagePortal , 'manage_overview' )
+    manage_overview = DTMLFile( 'dtml/explainActivityTool', globals() )
+
+    def __init__(self):
+        return Folder.__init__(self, ActivityTool.id)
+
+    # Filter content (ZMI))
+    def filtered_meta_types(self, user=None):
+        # Filters the list of available meta types.
+        all = ActivityTool.inheritedAttribute('filtered_meta_types')(self)
+        meta_types = []
+        for meta_type in self.all_meta_types():
+            if meta_type['name'] in self.allowed_types:
+                meta_types.append(meta_type)
+        return meta_types
+
     def initialize(self):
       global is_initialized
-      from Activity import RAMQueue, RAMDict, SQLDict, ZODBDict
+      from Activity import RAMQueue, RAMDict, SQLDict
       # Initialize each queue
       for activity in activity_list:
         activity.initialize(self)
@@ -187,10 +218,10 @@ class ActivityTool (UniqueObject, PortalFolder):
           return 1
       return 0
 
-    def activate(self, object, activity, **kw):
+    def activate(self, object, activity, active_process, **kw):
       global is_initialized
       if not is_initialized: self.initialize()
-      return ActiveWrapper(object, activity, **kw)
+      return ActiveWrapper(object, activity, active_process, **kw)
 
     def flush(self, object, invoke=0, **kw):
       global is_initialized
@@ -203,10 +234,11 @@ class ActivityTool (UniqueObject, PortalFolder):
     def invoke(self, message):
       message(self)
 
-    def newMessage(self, activity, path, activity_kw, method_id, *args, **kw):
+    def newMessage(self, activity, path, active_process, activity_kw, method_id, *args, **kw):
+      # Some Security Cheking should be made here XXX
       global is_initialized
       if not is_initialized: self.initialize()
-      activity_dict[activity].queueMessage(self, Message(path, activity_kw, method_id, args, kw))
+      activity_dict[activity].queueMessage(self, Message(path, active_process, activity_kw, method_id, args, kw))
 
     def manageInvoke(self, object_path, method_id, REQUEST=None):
       """
@@ -240,4 +272,21 @@ class ActivityTool (UniqueObject, PortalFolder):
         message_list += activity.getMessageList(self)
       return message_list
 
+    security.declareProtected( CMFCorePermissions.ManagePortal , 'newActiveProcess' )
+    def newActiveProcess(self):
+      from ActiveProcess import addActiveProcess
+      new_id = str(self.generateNewId())
+      addActiveProcess(self, new_id)
+      return self._getOb(new_id)
+
+    def reindexObject(self):
+      self.immediateReindexObject()
+
+    def getActiveProcess(self):
+      REQUEST = get_request()
+      if REQUEST.active_process:
+        return self.unrestrictedTraverse(REQUEST.active_process)
+      return None
+
+
 InitializeClass(ActivityTool)
diff --git a/product/CMFActivity/__init__.py b/product/CMFActivity/__init__.py
index e2f9280eebe6abc41109ebfac4b73a37cc2c9ad2..7ccc9d0c5bda69a9ffff58c69b0766930c3775f8 100755
--- a/product/CMFActivity/__init__.py
+++ b/product/CMFActivity/__init__.py
@@ -42,8 +42,8 @@ document_classes = generateInitFiles(this_module, globals())
 from Products.ERP5Type.Utils import initializeProduct, updateGlobals
 
 # Define object classes and tools
-import ActivityTool
-object_classes = ()
+import ActivityTool, ActiveProcess
+object_classes = (ActiveProcess.ActiveProcess, )
 portal_tools = (ActivityTool.ActivityTool,)
 content_classes = ()
 content_constructors = ()
diff --git a/product/CMFActivity/dtml/ActiveProcess_add.dtml b/product/CMFActivity/dtml/ActiveProcess_add.dtml
new file mode 100755
index 0000000000000000000000000000000000000000..65505d698903d01e74dca5d12f32b202c5b9afd4
--- /dev/null
+++ b/product/CMFActivity/dtml/ActiveProcess_add.dtml
@@ -0,0 +1,84 @@
+<dtml-var manage_page_header>
+
+<dtml-var "manage_form_title(this(), _,
+           form_title='Add Category',
+           help_product='ERP5',
+           help_topic='Category_Add.stx'
+	   )">
+<p class="form-help">
+A Folder contains other objects. Use Folders to organize your
+web objects in to logical groups. The <em>create public interface</em>
+option creates an index document inside the Folder to give the
+Folder a default HTML representation. The <em>create user folder</em>
+option creates a User Folder inside the Folder to hold authorization
+information for the Folder.
+</p>
+
+<FORM ACTION="addActiveProcess" METHOD="POST">
+
+<table cellspacing="0" cellpadding="2" border="0">
+  <tr>
+    <td align="left" valign="top">
+    <div class="form-label">
+    Id
+    </div>
+    </td>
+    <td align="left" valign="top">
+    <input type="text" name="id" size="40" />
+    </td>
+  </tr>
+
+  <tr>
+    <td align="left" valign="top">
+    <div class="form-optional">
+    Title
+    </div>
+    </td>
+    <td align="left" valign="top">
+    <input type="text" name="title" size="40" />
+    </td>
+  </tr>
+<dtml-if
+ "_.SecurityCheckPermission('Add Documents, Images, and Files',this())">
+  <tr>
+    <td align="left" valign="top">
+    </td>
+    <td align="left" valign="top">
+    <div class="form-text">
+    <input type="checkbox" name="createPublic:int" value="1"
+     id="cbCreatePublic">
+     <label for="cbCreatePublic">Create public interface</label>
+    </div>
+    </td>
+  </tr>
+</dtml-if>
+
+<dtml-if 
+ "_.SecurityCheckPermission('Add User Folders',this())">
+  <tr>
+    <td align="left" valign="top">
+    </td>
+    <td align="left" valign="top">
+    <div class="form-text">
+    <input type="checkbox" name="createUserF:int" value="1" 
+     id="cbCreateUserF"> 
+     <label for="cbCreateUserF">Create user folder</label>
+    </div>
+    </td>
+  </tr>
+</dtml-if>
+
+  <tr>
+    <td align="left" valign="top">
+    </td>
+    <td align="left" valign="top">
+    <div class="form-element">
+    <input class="form-element" type="submit" name="submit" 
+     value="Add" /> 
+    </div>
+    </td>
+  </tr>
+</table>
+</form>
+
+<dtml-var manage_page_footer>
diff --git a/product/CMFActivity/dtml/explainActivityTool.dtml b/product/CMFActivity/dtml/explainActivityTool.dtml
new file mode 100755
index 0000000000000000000000000000000000000000..9e59bafc3d31bb3c0d667a80fb7a8247e4657daa
--- /dev/null
+++ b/product/CMFActivity/dtml/explainActivityTool.dtml
@@ -0,0 +1,6 @@
+<dtml-var manage_page_header>
+<dtml-var manage_tabs>
+
+<p>Explain CategoryTool</p>
+
+<dtml-var manage_page_footer>