[jboss-svn-commits] JBoss Portal SVN: r5180 - in trunk: common/src/main/org/jboss/portal/common common/src/main/org/jboss/portal/common/invocation common/src/main/org/jboss/portal/common/util core core/src/main/org/jboss/portal/core/impl/model/instance core/src/main/org/jboss/portal/core/impl/portlet/state core/src/main/org/jboss/portal/core/metadata core/src/main/org/jboss/portal/core/portlet/management core/src/main/org/jboss/portal/test/core/model/instance core/src/main/org/jboss/portal/test/core/state core/src/resources/portal-core-sar core/src/resources/portal-core-sar/META-INF core/src/resources/portal-core-test-jar/org/jboss/portal/test/core core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/model/instance core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/state federation/src/main/org/jboss/portal/federation/impl portlet portlet/src/main/org/jboss/portal/portlet portlet/src/main/org/jboss/portal/portlet/container portlet/src/main/org/jboss/porta! l/portlet/impl portlet/src/main/org/jboss/portal/portlet/impl/state portlet/src/main/org/jboss/portal/portlet/impl/state/consumer portlet/src/main/org/jboss/portal/portlet/impl/state/producer portlet/src/main/org/jboss/portal/portlet/invocation portlet/src/main/org/jboss/portal/portlet/spi portlet/src/main/org/jboss/portal/portlet/state portlet/src/main/org/jboss/portal/portlet/state/consumer portlet/src/main/org/jboss/portal/portlet/state/producer portlet/src/main/org/jboss/portal/portlet/stateful portlet/src/main/org/jboss/portal/portlet/support/spi portlet/src/main/org/jboss/portal/portlet/test portlet/src/main/org/jboss/portal/portlet/test/support portlet/src/main/org/jboss/portal/portlet/test/support/info portlet/src/main/org/jboss/portal/test/portlet/state portlet/src/resources/tck-sar/META-INF portlet/src/resources/test-sar/META-INF server/src/main/org/jboss/portal/server/impl server/src/main/org/jboss/portal/server/impl/invocation wsrp/src/main/org/jboss/portal/test! /wsrp/v1/consumer wsrp/src/main/org/jboss/portal/wsrp/consumer wsrp/src/main/org/jboss/portal/wsrp/producer wsrp/src/resources/portal-wsrp-sar/META-INF wsrp/src/resources/test-wsrp-producer-sar/META-INF

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Tue Sep 12 12:53:18 EDT 2006


Author: julien at jboss.com
Date: 2006-09-12 12:51:45 -0400 (Tue, 12 Sep 2006)
New Revision: 5180

Added:
   trunk/common/src/main/org/jboss/portal/common/NotYetImplemented.java
   trunk/common/src/main/org/jboss/portal/common/invocation/EmptyInterceptorStackFactory.java
   trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/ProducerPortletInvoker.java
   trunk/core/src/main/org/jboss/portal/test/core/state/ProducerTestCase.java
   trunk/portlet/src/main/org/jboss/portal/portlet/PortletClonedEvent.java
   trunk/portlet/src/main/org/jboss/portal/portlet/PortletContext.java
   trunk/portlet/src/main/org/jboss/portal/portlet/PortletInvoker.java
   trunk/portlet/src/main/org/jboss/portal/portlet/RenderURL.java
   trunk/portlet/src/main/org/jboss/portal/portlet/StateEvent.java
   trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/
   trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/StateConverterService.java
   trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/StateManagementPolicyService.java
   trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/consumer/
   trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/consumer/ConsumerPersistenceManagerService.java
   trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/producer/
   trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/producer/ProducerPersistenceManagerService.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/InvalidStateIdException.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/NoSuchStateException.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/PortletClonedEvent.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/PortletModifiedEvent.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/PropertyMap.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/SimplePropertyMap.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/StateConverter.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/StateManagementPolicy.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/
   trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerPersistenceManager.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerPortletInvoker.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerState.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerStateContext.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerPersistenceManager.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerPortletInvoker.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerState.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerStateContext.java
   trunk/portlet/src/main/org/jboss/portal/portlet/stateful/
   trunk/portlet/src/main/org/jboss/portal/portlet/stateful/PortletInvoker.java
   trunk/portlet/src/main/org/jboss/portal/portlet/test/ActionContextImpl.java
   trunk/portlet/src/main/org/jboss/portal/portlet/test/InstanceContextImpl.java
   trunk/portlet/src/main/org/jboss/portal/portlet/test/UserContextImpl.java
   trunk/portlet/src/main/org/jboss/portal/portlet/test/support/info/MetaInfoSupport.java
   trunk/portlet/src/main/org/jboss/portal/test/portlet/state/AbstractStatefulPortletInvokerTestCase.java
   trunk/portlet/src/main/org/jboss/portal/test/portlet/state/ConsumerStatefulPortletInvokerTestCase.java
   trunk/portlet/src/main/org/jboss/portal/test/portlet/state/LocalStoreConsumerStatefulPortletInvokerTestCase.java
   trunk/portlet/src/main/org/jboss/portal/test/portlet/state/LocalStoreProducerStatefulPortletInvokerTestCase.java
   trunk/portlet/src/main/org/jboss/portal/test/portlet/state/ProducerStatefulPortletInvokerTestCase.java
   trunk/portlet/src/main/org/jboss/portal/test/portlet/state/RemoteStoreConsumerStatefulPortletInvokerTestCase.java
   trunk/portlet/src/main/org/jboss/portal/test/portlet/state/RemoteStoreProducerStatefulPortletInvokerTestCase.java
   trunk/server/src/main/org/jboss/portal/server/impl/MapAttributeResolver.java
   trunk/server/src/main/org/jboss/portal/server/impl/invocation/JBossInterceptorStackFactory.java
Removed:
   trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/StatefulPortletInvoker.java
   trunk/core/src/main/org/jboss/portal/test/core/state/StatefulPortletInvokerTestCase.java
   trunk/core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/prefs/
   trunk/portlet/src/main/org/jboss/portal/portlet/PortletInvoker.java
   trunk/portlet/src/main/org/jboss/portal/portlet/RenderURL.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/PropertyMap.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/SimplePropertyMap.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/InvalidStateIdException.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/NoSuchStateException.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/State.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StateStore.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StatefulPortletInvoker.java
   trunk/portlet/src/main/org/jboss/portal/portlet/test/support/state/
   trunk/portlet/src/main/org/jboss/portal/test/portlet/state/StatefulPortletInvokerTestCase.java
   trunk/server/src/main/org/jboss/portal/server/impl/JBossInterceptorStackFactory.java
Modified:
   trunk/common/src/main/org/jboss/portal/common/invocation/InterceptorStackFactory.java
   trunk/common/src/main/org/jboss/portal/common/util/Tools.java
   trunk/core/build.xml
   trunk/core/src/main/org/jboss/portal/core/impl/model/instance/InstanceContextImpl.java
   trunk/core/src/main/org/jboss/portal/core/impl/model/instance/InstanceImpl.java
   trunk/core/src/main/org/jboss/portal/core/impl/model/instance/PersistentInstanceContainer.java
   trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/PersistentState.java
   trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/PersistentStateStore.java
   trunk/core/src/main/org/jboss/portal/core/metadata/InstanceMetaData.java
   trunk/core/src/main/org/jboss/portal/core/portlet/management/PortletManagerBean.java
   trunk/core/src/main/org/jboss/portal/test/core/model/instance/InstanceContainerTestCase.java
   trunk/core/src/main/org/jboss/portal/test/core/state/SimpleInstanceContext.java
   trunk/core/src/resources/portal-core-sar/META-INF/jboss-service.xml
   trunk/core/src/resources/portal-core-sar/portal-aop.xml
   trunk/core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/model/instance/jboss-beans.xml
   trunk/core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/state/jboss-beans.xml
   trunk/federation/src/main/org/jboss/portal/federation/impl/FederatedPortletInvokerService.java
   trunk/federation/src/main/org/jboss/portal/federation/impl/FederatingPortletInvokerService.java
   trunk/portlet/build.xml
   trunk/portlet/src/main/org/jboss/portal/portlet/container/PortletContainerInvoker.java
   trunk/portlet/src/main/org/jboss/portal/portlet/invocation/PortletInvocation.java
   trunk/portlet/src/main/org/jboss/portal/portlet/spi/InstanceContext.java
   trunk/portlet/src/main/org/jboss/portal/portlet/state/AbstractPropertyContext.java
   trunk/portlet/src/main/org/jboss/portal/portlet/support/spi/InstanceContextSupport.java
   trunk/portlet/src/main/org/jboss/portal/portlet/support/spi/PortletInvocationContextSupport.java
   trunk/portlet/src/main/org/jboss/portal/portlet/test/PortletController.java
   trunk/portlet/src/main/org/jboss/portal/portlet/test/TestPortletInvoker.java
   trunk/portlet/src/main/org/jboss/portal/portlet/test/support/PortletInvokerSupport.java
   trunk/portlet/src/main/org/jboss/portal/portlet/test/support/PortletSupport.java
   trunk/portlet/src/main/org/jboss/portal/portlet/test/support/info/PortletInfoSupport.java
   trunk/portlet/src/resources/tck-sar/META-INF/jboss-service.xml
   trunk/portlet/src/resources/test-sar/META-INF/jboss-service.xml
   trunk/wsrp/src/main/org/jboss/portal/test/wsrp/v1/consumer/MarkupTestCase.java
   trunk/wsrp/src/main/org/jboss/portal/wsrp/consumer/WSRPConsumerImpl.java
   trunk/wsrp/src/main/org/jboss/portal/wsrp/producer/MarkupHandler.java
   trunk/wsrp/src/resources/portal-wsrp-sar/META-INF/jboss-service.xml
   trunk/wsrp/src/resources/test-wsrp-producer-sar/META-INF/jboss-service.xml
Log:
implementing state handling on the consumer, still more work to do, but the main stuff is here.

Added: trunk/common/src/main/org/jboss/portal/common/NotYetImplemented.java
===================================================================
--- trunk/common/src/main/org/jboss/portal/common/NotYetImplemented.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/common/src/main/org/jboss/portal/common/NotYetImplemented.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,39 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.common;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class NotYetImplemented extends UnsupportedOperationException
+{
+   public NotYetImplemented()
+   {
+      super("Not yet implemented");
+   }
+
+   public NotYetImplemented(String featureName)
+   {
+      super("Feature : " + featureName + " is not yet implemented");
+   }
+}

Added: trunk/common/src/main/org/jboss/portal/common/invocation/EmptyInterceptorStackFactory.java
===================================================================
--- trunk/common/src/main/org/jboss/portal/common/invocation/EmptyInterceptorStackFactory.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/common/src/main/org/jboss/portal/common/invocation/EmptyInterceptorStackFactory.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,47 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.common.invocation;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class EmptyInterceptorStackFactory implements InterceptorStackFactory
+{
+
+   public static final InterceptorStack EMPTY_STACK = new InterceptorStack()
+   {
+      public int getLength()
+      {
+         return 0;
+      }
+      public Interceptor getInterceptor(int index) throws ArrayIndexOutOfBoundsException
+      {
+         throw new ArrayIndexOutOfBoundsException();
+      }
+   };
+
+   public InterceptorStack getInterceptorStack()
+   {
+      return EMPTY_STACK;
+   }
+}

Modified: trunk/common/src/main/org/jboss/portal/common/invocation/InterceptorStackFactory.java
===================================================================
--- trunk/common/src/main/org/jboss/portal/common/invocation/InterceptorStackFactory.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/common/src/main/org/jboss/portal/common/invocation/InterceptorStackFactory.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -21,8 +21,6 @@
 */
 package org.jboss.portal.common.invocation;
 
-import org.jboss.portal.common.invocation.InterceptorStack;
-
 /**
  * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
  * @version $Revision: 1.1 $

Modified: trunk/common/src/main/org/jboss/portal/common/util/Tools.java
===================================================================
--- trunk/common/src/main/org/jboss/portal/common/util/Tools.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/common/src/main/org/jboss/portal/common/util/Tools.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -776,12 +776,30 @@
 
    public static Object clone(Serializable serializable) throws IOException, ClassNotFoundException
    {
+      return unserialize(serialize(serializable));
+   }
+
+   public static byte[] serialize(Serializable serializable) throws IllegalArgumentException, IOException
+   {
+      if (serializable == null)
+      {
+         throw new IllegalArgumentException("No null serializable accepted");
+      }
       ByteArrayOutputStream baos = new ByteArrayOutputStream();
       ObjectOutputStream oos = new ObjectOutputStream(baos);
       oos.writeObject(serializable);
       oos.close();
-      ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+      return baos.toByteArray();
+   }
+
+   public static Serializable unserialize(byte[] bytes) throws IllegalArgumentException, IOException, ClassNotFoundException
+   {
+      if (bytes == null)
+      {
+         throw new IllegalArgumentException("No null serializable accepted");
+      }
+      ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
       ObjectInputStream ois = new ObjectInputStream(bais);
-      return ois.readObject();
+      return (Serializable)ois.readObject();
    }
 }
\ No newline at end of file

Modified: trunk/core/build.xml
===================================================================
--- trunk/core/build.xml	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/build.xml	2006-09-12 16:51:45 UTC (rev 5180)
@@ -533,9 +533,8 @@
          </x-sysproperty>
          <x-test>
             <test todir="${test.reports}" name="org.jboss.portal.test.core.model.instance.InstanceContainerTestCase"/>
-            <test todir="${test.reports}" name="org.jboss.portal.test.core.state.StatefulPortletInvokerTestCase"/>
-            <test todir="${test.reports}"
-                  name="org.jboss.portal.test.core.deployment.JBossApplicationMetaDataFactoryTestCase"/>
+            <test todir="${test.reports}" name="org.jboss.portal.test.core.state.ProducerTestCase"/>
+            <test todir="${test.reports}" name="org.jboss.portal.test.core.deployment.JBossApplicationMetaDataFactoryTestCase"/>
          </x-test>
          <x-classpath>
             <pathelement location="${build.lib}/portal-core-lib.jar"/>

Modified: trunk/core/src/main/org/jboss/portal/core/impl/model/instance/InstanceContextImpl.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/core/impl/model/instance/InstanceContextImpl.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/core/impl/model/instance/InstanceContextImpl.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -23,6 +23,10 @@
 
 import org.jboss.portal.portlet.spi.InstanceContext;
 import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.state.PortletClonedEvent;
+import org.jboss.portal.portlet.state.PortletModifiedEvent;
+import org.jboss.portal.portlet.StateEvent;
+import org.jboss.portal.portlet.PortletContext;
 import org.jboss.portal.core.model.instance.Instance;
 
 /**
@@ -34,7 +38,7 @@
 
    protected final Instance instance;
    protected final AccessMode accessMode;
-   protected String cloneId;
+   protected PortletContext clonedContext;
 
    public InstanceContextImpl(Instance instance, AccessMode accessMode)
    {
@@ -51,18 +55,21 @@
       return instance.getId();
    }
 
-   public void portletCloned(String cloneId)
+   public AccessMode getAccessMode()
    {
-      this.cloneId = cloneId;
+      return accessMode;
    }
 
-   public void portletCloned(byte[] state)
+   public void onStateEvent(StateEvent event)
    {
-      throw new UnsupportedOperationException("NYI");
+      if (event instanceof PortletClonedEvent)
+      {
+         PortletClonedEvent pce = (PortletClonedEvent)event;
+         clonedContext = pce.getClonedContext();
+      }
+      else if (event instanceof PortletModifiedEvent)
+      {
+         throw new UnsupportedOperationException("todo");
+      }
    }
-
-   public AccessMode getAccessMode()
-   {
-      return accessMode;
-   }
 }

Modified: trunk/core/src/main/org/jboss/portal/core/impl/model/instance/InstanceImpl.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/core/impl/model/instance/InstanceImpl.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/core/impl/model/instance/InstanceImpl.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -30,6 +30,7 @@
 import org.jboss.portal.portlet.Portlet;
 import org.jboss.portal.portlet.PortletInvoker;
 import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.PortletContext;
 import org.jboss.portal.portlet.invocation.PortletInvocation;
 import org.jboss.portal.portlet.spi.UserContext;
 import org.jboss.portal.portlet.state.AccessMode;
@@ -197,7 +198,7 @@
       if (!modifiable)
       {
          // Clone the portlet
-         String clonedPortletId = portletInvoker.createClone(portletRef);
+         String clonedPortletId = portletInvoker.createClone(new PortletContext(portletRef)).getId();
 
          // Update the state
          portletRef = clonedPortletId;
@@ -207,21 +208,21 @@
       }
 
       //
-      portletInvoker.setProperties(portletRef, changes);
+      portletInvoker.setProperties(new PortletContext(portletRef), changes);
    }
 
    public PropertyMap getProperties() throws PortletInvokerException
    {
       PersistentInstanceContainer container = (PersistentInstanceContainer)context.getContainer();
       PortletInvoker invoker = container.getPortletInvoker();
-      return invoker.getProperties(portletRef);
+      return invoker.getProperties(new PortletContext(portletRef));
    }
 
    public PropertyMap getProperties(Set keys) throws PortletInvokerException
    {
       PersistentInstanceContainer container = (PersistentInstanceContainer)context.getContainer();
       PortletInvoker invoker = container.getPortletInvoker();
-      return invoker.getProperties(portletRef, keys);
+      return invoker.getProperties(new PortletContext(portletRef), keys);
    }
 
    public void invoke(PortletInvocation invocation) throws PortletInvokerException
@@ -275,30 +276,30 @@
       try
       {
          invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.INSTANCE_ID_ATTRIBUTE, instanceId);
-         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, portletId);
+         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, new PortletContext(portletId));
          invocation.setInstanceContext(instanceContext);
 
          // Perform invocation
-         container.getPortletInvoker().invoke(invocation);
+         container.invoke(invocation);
       }
       finally
       {
          // Reset state before invocation
          invocation.removeAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.INSTANCE_ID_ATTRIBUTE);
-         invocation.removeAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE);
+         invocation.removeAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE);
          invocation.setInstanceContext(null);
 
          // Create user instance if a clone operation occured
-         if (instanceContext.accessMode == AccessMode.CLONE_BEFORE_WRITE && instanceContext.cloneId != null)
+         if (instanceContext.accessMode == AccessMode.CLONE_BEFORE_WRITE && instanceContext.clonedContext != null)
          {
             try
             {
                if (debug)
                {
                  log.debug("About to reference clone of (" + instanceId + "," + portletId +
-                           ") having id " + instanceContext.cloneId + " for user " + userId);
+                           ") having id " + instanceContext.clonedContext + " for user " + userId);
                }
-               UserInstance userInstance = new UserInstance(userId, instanceContext.cloneId);
+               UserInstance userInstance = new UserInstance(userId, instanceContext.clonedContext.getId());
                session.persist(userInstance);
                userInstance.setInstance(this);
                userInstances.add(userInstance);

Modified: trunk/core/src/main/org/jboss/portal/core/impl/model/instance/PersistentInstanceContainer.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/core/impl/model/instance/PersistentInstanceContainer.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/core/impl/model/instance/PersistentInstanceContainer.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -33,6 +33,8 @@
 import org.jboss.portal.core.model.instance.NoSuchInstanceException;
 import org.jboss.portal.portlet.PortletInvoker;
 import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.PortletContext;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
 import org.jboss.portal.portlet.state.DestroyCloneFailure;
 import org.jboss.portal.security.PortalPermission;
 import org.jboss.portal.security.PortalPermissionCollection;
@@ -47,6 +49,10 @@
 import org.jboss.portal.security.spi.provider.PermissionRepository;
 import org.jboss.portal.security.spi.provider.SecurityConfigurationException;
 import org.jboss.portal.jems.hibernate.ObjectContextualizer;
+import org.jboss.portal.common.invocation.InterceptorStackFactory;
+import org.jboss.portal.common.invocation.InvocationHandler;
+import org.jboss.portal.common.invocation.Invocation;
+import org.jboss.portal.common.invocation.InvocationException;
 
 import javax.naming.InitialContext;
 import java.util.Collection;
@@ -70,6 +76,9 @@
 {
 
    /** . */
+   protected InterceptorStackFactory stackFactory;
+
+   /** . */
    protected SessionFactory sessionFactory;
 
    /** . */
@@ -93,6 +102,24 @@
    /** If true clone the portlet on an instance creation. */
    protected boolean cloneOnCreate;
 
+   /** . */
+   protected InvocationHandler handler = new InvocationHandler()
+   {
+      public void invoke(Invocation invocation) throws Exception, InvocationException
+      {
+         PortletInvocation portletInvocation = (PortletInvocation)invocation;
+         try
+         {
+            portletInvocation.setHandler(null);
+            portletInvoker.invoke(portletInvocation);
+         }
+         finally
+         {
+            portletInvocation.setHandler(this);
+         }
+      }
+   };
+
    public PersistentInstanceContainer()
    {
       ctx = new ContainerContext()
@@ -117,6 +144,16 @@
       this.cloneOnCreate = cloneOnCreate;
    }
 
+   public InterceptorStackFactory getStackFactory()
+   {
+      return stackFactory;
+   }
+
+   public void setStackFactory(InterceptorStackFactory stackFactory)
+   {
+      this.stackFactory = stackFactory;
+   }
+
    public PortletInvoker getPortletInvoker()
    {
       return portletInvoker;
@@ -219,7 +256,7 @@
       if (clone)
       {
          // Clone the portlet state now and update the instance
-         String clonedPortletId = portletInvoker.createClone(portletId);
+         String clonedPortletId = portletInvoker.createClone(new PortletContext(portletId)).getId();
          instance.setPortletRef(clonedPortletId);
          instance.setModifiable(true);
       }
@@ -319,6 +356,35 @@
       return session.createQuery("from InstanceImpl").list();
    }
 
+   void invoke(PortletInvocation invocation) throws PortletInvokerException
+   {
+      InvocationHandler prevHandler = invocation.getHandler();
+      try
+      {
+         invocation.setHandler(handler);
+         invocation.invoke(stackFactory.getInterceptorStack());
+      }
+      catch (Exception e)
+      {
+         if (e instanceof PortletInvokerException)
+         {
+            throw (PortletInvokerException)e;
+         }
+         else if (e instanceof RuntimeException)
+         {
+            throw (RuntimeException)e;
+         }
+         else
+         {
+            throw new PortletInvokerException(e);
+         }
+      }
+      finally
+      {
+         invocation.setHandler(prevHandler);
+      }
+   }
+
    public JBossAuthorizationDomainRegistry getAuthorizationDomainRegistry()
    {
       return authorizationDomainRegistry;

Modified: trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/PersistentState.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/PersistentState.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/PersistentState.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -21,7 +21,7 @@
 */
 package org.jboss.portal.core.impl.portlet.state;
 
-import org.jboss.portal.portlet.state.producer.State;
+import org.jboss.portal.portlet.state.producer.ProducerStateContext;
 import org.jboss.portal.portlet.state.PropertyMap;
 import org.jboss.portal.portlet.state.AbstractPropertyMap;
 import org.jboss.portal.common.value.Value;
@@ -38,7 +38,7 @@
  * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
  * @version $Revision$
  */
-public class PersistentState implements State
+public class PersistentState 
 {
 
    /** The primary key. */
@@ -65,6 +65,9 @@
    /** The state that we cloned from. */
    protected PersistentState parent;
 
+   /** . */
+   private ProducerStateContext ctx;
+
    public PersistentState()
    {
       this.key = null;
@@ -75,6 +78,7 @@
       this.registrationId = null;
       this.children = null;
       this.parent = null;
+      this.ctx = null;
    }
 
    public PersistentState(String portletId, PropertyMap propertyMap)
@@ -87,6 +91,7 @@
       this.registrationId = null;
       this.children = new HashSet();
       this.parent = null;
+      this.ctx = null;
 
       //
       for (Iterator i = propertyMap.keySet().iterator(); i.hasNext();)
@@ -109,7 +114,7 @@
 
    public String getId()
    {
-      return "" + key;
+      return key.toString();
    }
 
    public String getPortletId()
@@ -132,27 +137,6 @@
       this.entries = entries;
    }
 
-   public PropertyMap getProperties()
-   {
-      PropertyMap props = new AbstractPropertyMap()
-      {
-         protected Map getDelegate()
-         {
-            return entries;
-         }
-         protected Object getInternalValue(Object value)
-         {
-            throw new IllegalArgumentException("Immutable");
-         }
-         protected Object getExternalValue(Object value)
-         {
-            PersistentStateEntry entry = (PersistentStateEntry)value;
-            return entry.getValue();
-         }
-      };
-      return props;
-   }
-
    public Date getCreationTime()
    {
       return creationTime;
@@ -202,4 +186,29 @@
    {
       this.parent = parent;
    }
+
+   public ProducerStateContext getContext()
+   {
+      if (ctx == null)
+      {
+         PropertyMap props = new AbstractPropertyMap()
+         {
+            protected Map getDelegate()
+            {
+               return entries;
+            }
+            protected Object getInternalValue(Object value)
+            {
+               throw new IllegalArgumentException("Immutable");
+            }
+            protected Object getExternalValue(Object value)
+            {
+               PersistentStateEntry entry = (PersistentStateEntry)value;
+               return entry.getValue();
+            }
+         };
+         ctx = new ProducerStateContext(key.toString(), portletId, props);
+      }
+      return ctx;
+   }
 }

Modified: trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/PersistentStateStore.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/PersistentStateStore.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/PersistentStateStore.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -21,10 +21,10 @@
 */
 package org.jboss.portal.core.impl.portlet.state;
 
-import org.jboss.portal.portlet.state.producer.StateStore;
-import org.jboss.portal.portlet.state.producer.State;
-import org.jboss.portal.portlet.state.producer.NoSuchStateException;
-import org.jboss.portal.portlet.state.producer.InvalidStateIdException;
+import org.jboss.portal.portlet.state.producer.ProducerPersistenceManager;
+import org.jboss.portal.portlet.state.producer.ProducerStateContext;
+import org.jboss.portal.portlet.state.NoSuchStateException;
+import org.jboss.portal.portlet.state.InvalidStateIdException;
 import org.jboss.portal.portlet.state.PropertyMap;
 import org.jboss.portal.common.value.Value;
 import org.jboss.portal.portlet.state.SimplePropertyMap;
@@ -40,7 +40,7 @@
  * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
  * @version $Revision$
  */
-public class PersistentStateStore extends AbstractJBossService implements StateStore
+public class PersistentStateStore extends AbstractJBossService implements ProducerPersistenceManager
 {
 
    /** . */
@@ -59,18 +59,11 @@
       this.sessionFactoryJNDIName = sessionFactoryJNDIName;
    }
 
-   public State loadState(String id) throws InvalidStateIdException, NoSuchStateException
+   public ProducerStateContext loadState(String id) throws InvalidStateIdException, NoSuchStateException
    {
-      if(id == null)
-      {
-         throw new IllegalArgumentException("id cannot be null");
-      }
-
-      //
       Session session = getCurrentSession();
-
-      //
-      return lookup(session, id);
+      PersistentState persistentState = loadState(session, id);
+      return persistentState.getContext();
    }
 
    public String createState(String portletId, PropertyMap propertyMap)
@@ -109,10 +102,8 @@
 
       //
       Session session = getCurrentSession();
+      PersistentState parentState = loadState(session, stateId);
 
-      //
-      PersistentState parentState = (PersistentState)loadState(stateId);
-
       // Create the persistent state
       PersistentState state = new PersistentState(parentState.getPortletId(), propertyMap);
       session.persist(state);
@@ -138,13 +129,10 @@
 
       //
       Session session = getCurrentSession();
+      PersistentState parentState = loadState(session, stateId);
 
-      //
-      PersistentState parentState = (PersistentState)loadState(stateId);
-
-      //
       // Create the persistent state
-      PersistentState state = new PersistentState(parentState.getPortletId(), new SimplePropertyMap(parentState.getProperties()));
+      PersistentState state = new PersistentState(parentState.getPortletId(), new SimplePropertyMap(parentState.getContext().getProperties()));
       session.persist(state);
 
       // Make the association
@@ -162,11 +150,9 @@
    public void updateState(String stateId, PropertyMap propertyMap) throws InvalidStateIdException, NoSuchStateException
    {
       Session session = getCurrentSession();
+      PersistentState state = loadState(session, stateId);
 
       //
-      PersistentState state = lookup(session, stateId);
-
-      //
       state.entries.clear();
       for (Iterator i = propertyMap.keySet().iterator(); i.hasNext();)
       {
@@ -189,10 +175,8 @@
 
       //
       Session session = getCurrentSession();
+      PersistentState state = loadState(session, stateId);
 
-      //
-      PersistentState state = lookup(session, stateId);
-
       // Efficiently set the children parent to null
       String update = "update PersistentState p set p.parent=NULL where p.parent=:parent";
       Query query = session.createQuery(update).setLong("parent", state.getKey().longValue());
@@ -218,26 +202,30 @@
       return sessionFactory.getCurrentSession();
    }
 
-   private PersistentState lookup(Session session, String stateId) throws NoSuchStateException, InvalidStateIdException
+   private PersistentState loadState(Session session, String stateId) throws NoSuchStateException, InvalidStateIdException
    {
-      Long key;
+      if (stateId == null)
+      {
+         throw new IllegalArgumentException("id cannot be null");
+      }
+
       try
       {
-         key = new Long(stateId);
+         Long key = new Long(stateId);
+         PersistentState state = (PersistentState)session.get(PersistentState.class, key);
+
+         //
+         if (state == null)
+         {
+            throw new NoSuchStateException(stateId);
+         }
+
+         //
+         return state;
       }
       catch (NumberFormatException e)
       {
          throw new InvalidStateIdException(e, stateId);
       }
-
-      //
-      PersistentState state = (PersistentState)session.get(PersistentState.class, key);
-      if (state == null)
-      {
-         throw new NoSuchStateException(stateId);
-      }
-
-      //
-      return state;
    }
 }

Copied: trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/ProducerPortletInvoker.java (from rev 5179, trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/StatefulPortletInvoker.java)
===================================================================
--- trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/StatefulPortletInvoker.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/ProducerPortletInvoker.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,51 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.core.impl.portlet.state;
+
+import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.PortletContext;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+import org.jboss.portal.common.invocation.InvocationException;
+
+import java.util.List;
+
+/**
+ * The subclass is used to be able to add AOP behavior.
+ *
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision$
+ */
+public class ProducerPortletInvoker extends org.jboss.portal.portlet.state.producer.ProducerPortletInvoker
+{
+   public PortletContext createClone(PortletContext portletContext) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      return super.createClone(portletContext);
+   }
+   public List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      return super.destroyClones(portletIds);
+   }
+   public void invoke(PortletInvocation invocation) throws PortletInvokerException, InvocationException
+   {
+      super.invoke(invocation);
+   }
+}


Property changes on: trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/ProducerPortletInvoker.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Deleted: trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/StatefulPortletInvoker.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/StatefulPortletInvoker.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/core/impl/portlet/state/StatefulPortletInvoker.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,50 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.core.impl.portlet.state;
-
-import org.jboss.portal.portlet.PortletInvokerException;
-import org.jboss.portal.portlet.invocation.PortletInvocation;
-import org.jboss.portal.common.invocation.InvocationException;
-
-import java.util.List;
-
-/**
- * The subclass is used to be able to add AOP behavior.
- *
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public class StatefulPortletInvoker extends org.jboss.portal.portlet.state.producer.StatefulPortletInvoker
-{
-   public String createClone(String portletId) throws PortletInvokerException
-   {
-      return super.createClone(portletId);
-   }
-   public List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
-   {
-      return super.destroyClones(portletIds);
-   }
-   public void invoke(PortletInvocation invocation) throws PortletInvokerException, InvocationException
-   {
-      super.invoke(invocation);
-   }
-}

Modified: trunk/core/src/main/org/jboss/portal/core/metadata/InstanceMetaData.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/core/metadata/InstanceMetaData.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/core/metadata/InstanceMetaData.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -23,8 +23,6 @@
 
 import org.jboss.portal.common.metadata.MetaData;
 import org.jboss.portal.common.util.XML;
-import org.jboss.portal.portlet.state.PropertyMap;
-import org.jboss.portal.portlet.state.SimplePropertyMap;
 import org.jboss.portal.portlet.state.PropertyChange;
 import org.jboss.portal.common.value.StringValue;
 import org.jboss.portal.common.value.Value;

Modified: trunk/core/src/main/org/jboss/portal/core/portlet/management/PortletManagerBean.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/core/portlet/management/PortletManagerBean.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/core/portlet/management/PortletManagerBean.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -26,7 +26,6 @@
 import org.jboss.portal.common.util.LocalizedString;
 import org.jboss.portal.common.value.Value;
 import org.jboss.portal.core.model.instance.InstanceContainer;
-import org.jboss.portal.core.model.instance.Instance;
 import org.jboss.portal.faces.matrix.Cell;
 import org.jboss.portal.faces.matrix.Row;
 import org.jboss.portal.faces.matrix.RowSetModel;

Modified: trunk/core/src/main/org/jboss/portal/test/core/model/instance/InstanceContainerTestCase.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/test/core/model/instance/InstanceContainerTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/test/core/model/instance/InstanceContainerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -19,11 +19,12 @@
 import org.jboss.portal.portlet.test.support.info.PreferencesInfoSupport;
 import org.jboss.portal.portlet.test.support.PortletInvokerSupport;
 import org.jboss.portal.portlet.test.support.PortletSupport;
-import org.jboss.portal.portlet.state.producer.StatefulPortletInvoker;
+import org.jboss.portal.portlet.state.producer.ProducerPortletInvoker;
 import org.jboss.portal.portlet.state.AbstractPropertyContext;
 import org.jboss.portal.portlet.state.PropertyChange;
 import org.jboss.portal.Mode;
 import org.jboss.portal.portlet.NoSuchPortletException;
+import org.jboss.portal.portlet.PortletContext;
 import org.jboss.portal.portlet.invocation.ActionInvocation;
 import org.jboss.portal.portlet.invocation.PortletInvocation;
 import org.jboss.portal.test.framework.embedded.DataSourceSupport;
@@ -31,7 +32,6 @@
 import org.jboss.portal.test.framework.junit.DatabaseTestSuite;
 import org.jboss.portal.test.framework.junit.TransactionAssert;
 import org.jboss.portal.test.framework.TestRuntimeContext;
-import org.jboss.portal.portlet.state.SimplePropertyMap;
 import org.jboss.portal.common.value.StringValue;
 import org.apache.log4j.Appender;
 import org.apache.log4j.ConsoleAppender;
@@ -98,13 +98,13 @@
    private PersistentInstanceContainer instanceContainer;
 
    /** . */
-   private PersistentStateStore stateStore;
+   private PersistentStateStore persistenceManager;
 
    /** . */
-   private StatefulPortletInvoker statefulPortletInvoker;
+   private ProducerPortletInvoker producer;
 
    /** . */
-   private PortletInvokerSupport nextPortletInvoker;
+   private PortletInvokerSupport portletContainer;
 
    public InstanceContainerTestCase(DataSourceSupport.Config config)
    {
@@ -146,34 +146,34 @@
       this.instanceContainer = instanceContainer;
    }
 
-   public PersistentStateStore getStateStore()
+   public PersistentStateStore getPersistenceManager()
    {
-      return stateStore;
+      return persistenceManager;
    }
 
-   public void setStateStore(PersistentStateStore stateStore)
+   public void setPersistenceManager(PersistentStateStore persistenceManager)
    {
-      this.stateStore = stateStore;
+      this.persistenceManager = persistenceManager;
    }
 
-   public StatefulPortletInvoker getStatefulPortletInvoker()
+   public ProducerPortletInvoker getProducer()
    {
-      return statefulPortletInvoker;
+      return producer;
    }
 
-   public void setStatefulPortletInvoker(StatefulPortletInvoker statefulPortletInvoker)
+   public void setProducer(ProducerPortletInvoker portletInvoker)
    {
-      this.statefulPortletInvoker = statefulPortletInvoker;
+      this.producer = portletInvoker;
    }
 
-   public PortletInvokerSupport getNextPortletInvoker()
+   public PortletInvokerSupport getPortletContainer()
    {
-      return nextPortletInvoker;
+      return portletContainer;
    }
 
-   public void setNextPortletInvoker(PortletInvokerSupport nextPortletInvoker)
+   public void setPortletContainer(PortletInvokerSupport portletContainer)
    {
-      this.nextPortletInvoker = nextPortletInvoker;
+      this.portletContainer = portletContainer;
    }
 
    protected void setUp() throws Exception
@@ -198,7 +198,7 @@
 
    public void testConfigureInstance() throws Exception
    {
-      nextPortletInvoker.addPortlet(new PortletSupport("MyPortlet")
+      portletContainer.addPortlet("MyPortlet", new PortletSupport()
       {
          {
             PreferencesInfoSupport prefs = info.getPreferencesSupport();
@@ -267,7 +267,7 @@
     */
    public void testCloneBeforeWrite() throws Exception
    {
-      nextPortletInvoker.addPortlet(new PortletSupport("MyPortlet")
+      portletContainer.addPortlet("MyPortlet", new PortletSupport()
       {
          {
             PreferencesInfoSupport prefs = info.getPreferencesSupport();
@@ -299,7 +299,7 @@
       List instances = session.createQuery("from InstanceImpl").list();
       assertEquals(1, instances.size());
       InstanceImpl instanceImpl = (InstanceImpl)instances.get(0);
-      String ccpId = statefulPortletInvoker.unwrapCCPId(instanceImpl.getPortletRef());
+      String ccpId = producer.unwrapCCP(new PortletContext(instanceImpl.getPortletRef()));
       Long instanceStateKey = new Long(ccpId);
       PersistentState instanceState = (PersistentState)portletHibernateSupport.getCurrentSession().get(PersistentState.class, instanceStateKey);
       Set userInstances = instanceImpl.getUserInstances();
@@ -333,7 +333,7 @@
     */
    public void testCloneBeforeWriteRollback() throws Exception
    {
-      nextPortletInvoker.addPortlet(new PortletSupport("MyPortlet")
+      portletContainer.addPortlet("MyPortlet", new PortletSupport()
       {
          {
             PreferencesInfoSupport prefs = info.getPreferencesSupport();
@@ -377,7 +377,7 @@
 
    public void testCloneBeforeWriteThrowable() throws Exception
    {
-      nextPortletInvoker.addPortlet(new PortletSupport("MyPortlet")
+      portletContainer.addPortlet("MyPortlet", new PortletSupport()
       {
          {
             PreferencesInfoSupport prefs = info.getPreferencesSupport();
@@ -428,7 +428,7 @@
 
    public void testDeleteDestroyInstance() throws Exception
    {
-      nextPortletInvoker.addPortlet(new PortletSupport("MyPortlet")
+      portletContainer.addPortlet("MyPortlet", new PortletSupport()
       {
          {
             PreferencesInfoSupport prefs = info.getPreferencesSupport();
@@ -457,14 +457,14 @@
       TransactionAssert.beginTransaction();
       InstanceImpl instanceImpl = (InstanceImpl)instanceContainer.getInstance("MyInstance");
       String instancePortletRefId = instanceImpl.getPortletRef();
-      assertNotNull(statefulPortletInvoker.getPortlet(instancePortletRefId));
+      assertNotNull(producer.getPortlet(instancePortletRefId));
       assertNotNull(instance);
       Set children = instanceImpl.getUserInstances();
       assertNotNull(children);
       assertEquals(1, children.size());
       UserInstance userInstance = (UserInstance)children.iterator().next();
       String userPortletRefId = userInstance.getPortletRef();
-      assertNotNull(statefulPortletInvoker.getPortlet(userPortletRefId));
+      assertNotNull(producer.getPortlet(userPortletRefId));
       assertNotNull(userInstance);
       TransactionAssert.commitTransaction();
 
@@ -477,7 +477,7 @@
       TransactionAssert.beginTransaction();
       try
       {
-         statefulPortletInvoker.getPortlet(userPortletRefId);
+         producer.getPortlet(userPortletRefId);
          fail("Was expecting a NoSuchPortletException");
       }
       catch (NoSuchPortletException expected)
@@ -485,7 +485,7 @@
       }
       try
       {
-         statefulPortletInvoker.getPortlet(instancePortletRefId);
+         producer.getPortlet(instancePortletRefId);
          fail("Was expecting a NoSuchPortletException");
       }
       catch (NoSuchPortletException expected)

Copied: trunk/core/src/main/org/jboss/portal/test/core/state/ProducerTestCase.java (from rev 5179, trunk/core/src/main/org/jboss/portal/test/core/state/StatefulPortletInvokerTestCase.java)
===================================================================
--- trunk/core/src/main/org/jboss/portal/test/core/state/StatefulPortletInvokerTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/test/core/state/ProducerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,609 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.test.core.state;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.log4j.Appender;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.SimpleLayout;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
+import org.jboss.portal.test.framework.embedded.DataSourceSupport;
+import org.jboss.portal.test.framework.embedded.HibernateSupport;
+import org.jboss.portal.test.framework.junit.DatabaseTestSuite;
+import org.jboss.portal.test.framework.junit.TransactionAssert;
+import org.jboss.portal.test.framework.TestRuntimeContext;
+import org.jboss.portal.test.core.model.instance.SimpleActionContext;
+import org.jboss.portal.test.core.model.instance.SimpleUserContext;
+import org.jboss.portal.portlet.test.ValueMapAssert;
+import org.jboss.portal.core.impl.portlet.state.PersistentStateStore;
+import org.jboss.portal.core.impl.portlet.state.ProducerPortletInvoker;
+import org.jboss.portal.portlet.NoSuchPortletException;
+import org.jboss.portal.portlet.Portlet;
+import org.jboss.portal.portlet.PortletContext;
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.Mode;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+import org.jboss.portal.portlet.invocation.ActionInvocation;
+import org.jboss.portal.portlet.state.producer.ProducerState;
+import org.jboss.portal.portlet.state.producer.ProducerStateContext;
+import org.jboss.portal.portlet.state.AbstractPropertyContext;
+import org.jboss.portal.portlet.state.PropertyChange;
+import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.state.SimplePropertyMap;
+import org.jboss.portal.portlet.state.DestroyCloneFailure;
+import org.jboss.portal.portlet.test.support.info.PreferencesInfoSupport;
+import org.jboss.portal.portlet.test.support.PortletInvokerSupport;
+import org.jboss.portal.portlet.test.support.PortletSupport;
+import org.jboss.portal.common.value.StringValue;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision$
+ */
+public class ProducerTestCase extends TestCase
+{
+
+   static
+   {
+      Appender appender = new ConsoleAppender(new SimpleLayout());
+      Logger.getRoot().addAppender(appender);
+      Logger.getRoot().setLevel(Level.DEBUG);
+      Logger.getLogger("org.hibernate").setLevel(Level.ERROR);
+   }
+
+   public static TestSuite suite() throws Exception
+   {
+      URL configsURL = Thread.currentThread().getContextClassLoader().getResource("datasources.xml");
+      DataSourceSupport.Config[] configs = DataSourceSupport.Config.fromXML(configsURL);
+      DatabaseTestSuite suite = new DatabaseTestSuite(configs);
+      suite.addTestCase(ProducerTestCase.class);
+      return suite;
+   }
+
+   /** . */
+   private TestRuntimeContext runtimeContext;
+
+   /** . */
+   private DataSourceSupport.Config dsCfg;
+
+   /** . */
+   private HibernateSupport hibernateSupport;
+
+   /** . */
+   private PersistentStateStore persistenceManager;
+
+   /** . */
+   private ProducerPortletInvoker producer;
+
+   /** . */
+   private PortletInvokerSupport portletContainer;
+
+   public ProducerTestCase(DataSourceSupport.Config config)
+   {
+      this.dsCfg = config;
+   }
+
+   public HibernateSupport getHibernateSupport()
+   {
+      return hibernateSupport;
+   }
+
+   public void setHibernateSupport(HibernateSupport hibernateSupport)
+   {
+      this.hibernateSupport = hibernateSupport;
+   }
+
+   public PersistentStateStore getPersistenceManager()
+   {
+      return persistenceManager;
+   }
+
+   public void setPersistenceManager(PersistentStateStore persistenceManager)
+   {
+      this.persistenceManager = persistenceManager;
+   }
+
+   public ProducerPortletInvoker getProducer()
+   {
+      return producer;
+   }
+
+   public void setProducer(ProducerPortletInvoker producer)
+   {
+      this.producer = producer;
+   }
+
+   public PortletInvokerSupport getPortletContainer()
+   {
+      return portletContainer;
+   }
+
+   public void setPortletContainer(PortletInvokerSupport portletContainer)
+   {
+      this.portletContainer = portletContainer;
+   }
+
+   protected void setUp() throws Exception
+   {
+      runtimeContext = new TestRuntimeContext("org/jboss/portal/test/core/state/jboss-beans.xml");
+      runtimeContext.addBean("TestBean", this);
+      runtimeContext.addBean("DataSourceConfig", dsCfg);
+      runtimeContext.start();
+
+      portletContainer.addPortlet("SimplePortlet", new PortletSupport()
+      {
+         {
+            PreferencesInfoSupport prefs = info.getPreferencesSupport();
+            prefs.addPreference("abc", new StringValue("def"));
+         }
+         public void invoke(PortletInvocation invocation)
+         {
+            AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
+            props.update(new PropertyChange[]{PropertyChange.newUpdate("_abc", new StringValue("_def"))});
+         }
+      });
+
+      portletContainer.addPortlet("CloningPortlet", new PortletSupport()
+      {
+         {
+            PreferencesInfoSupport prefs = info.getPreferencesSupport();
+            prefs.addPreference("abc", new StringValue("def"));
+         }
+         public void invoke(PortletInvocation invocation)
+         {
+            AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
+            props.update(new PropertyChange[]{PropertyChange.newUpdate("_abc", new StringValue("_def"))});
+         }
+      });
+
+      portletContainer.addPortlet("CloneFailedCloningPortlet", new PortletSupport()
+      {
+         {
+            PreferencesInfoSupport prefs = info.getPreferencesSupport();
+            prefs.addPreference("abc", new StringValue("def"));
+         }
+         public void invoke(PortletInvocation invocation)
+         {
+            try
+            {
+               AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
+               props.update(new PropertyChange[]{PropertyChange.newUpdate("_abc", new StringValue("_def"))});
+               fail("Was expecting an IllegalStateException");
+            }
+            catch (IllegalStateException expected)
+            {
+            }
+         }
+      });
+
+      portletContainer.addPortlet("CloningPortletThrowingRuntimeException", new PortletSupport()
+      {
+         {
+            PreferencesInfoSupport prefs = info.getPreferencesSupport();
+            prefs.addPreference("abc", new StringValue("def"));
+         }
+         public void invoke(PortletInvocation invocation)
+         {
+            AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
+            props.update(new PropertyChange[]{PropertyChange.newUpdate("_abc", new StringValue("_def"))});
+            throw new RuntimeException("custom_message");
+         }
+      });
+   }
+
+   protected void tearDown() throws Exception
+   {
+      // Cleanup any pending transaction
+      TransactionAssert.endTransaction();
+
+      runtimeContext.stop();
+   }
+
+   public void testCloneNonExistingPortletWithinTx() throws Exception
+   {
+      try
+      {
+         TransactionAssert.beginTransaction();
+         producer.createClone(new PortletContext("UnknownPortlet"));
+         fail("Was expecting no such portlet exception");
+      }
+      catch (NoSuchPortletException e)
+      {
+         TransactionAssert.rollbackTransaction(true);
+      }
+
+      // todo check state
+
+//      try
+//      {
+//         TransactionAssert.beginTransaction();
+//         statefulPortletInvoker.createClone("_1");
+//         fail("Was expecting no such portlet exception");
+//      }
+//      catch (NoSuchPortletException e)
+//      {
+//         TransactionAssert.rollbackTransaction(true);
+//      }
+
+      // todo check state
+   }
+
+   public void testCloneNullPortletWithinTx() throws Exception
+   {
+      try
+      {
+         TransactionAssert.beginTransaction();
+         producer.createClone(null);
+         fail("Was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException expected)
+      {
+         TransactionAssert.rollbackTransaction(true);
+      }
+   }
+
+   public void testCloneExistingPortletWithinTx() throws Exception
+   {
+      // Clone a POP
+      TransactionAssert.beginTransaction();
+      PortletContext cloneCtx = producer.createClone(new PortletContext("SimplePortlet"));
+      TransactionAssert.commitTransaction();
+
+      // Check the clone state
+      TransactionAssert.beginTransaction();
+      assertTrue(cloneCtx.getId().startsWith("_"));
+      ProducerStateContext cloneState = persistenceManager.loadState(cloneCtx.getId().substring(1));
+      assertNotNull(cloneState);
+      assertEquals(cloneCtx.getId(), "_" + cloneState.getId());
+      assertEquals("SimplePortlet", cloneState.getPortletId());
+      PropertyMap cloneValues = cloneState.getProperties();
+      assertNotNull(cloneValues);
+      assertNotNull(cloneValues.keySet());
+      assertEquals(1, cloneValues.keySet().size());
+      assertEquals(new StringValue("def"), cloneValues.getProperty("abc"));
+      TransactionAssert.commitTransaction();
+
+      // Update CCP state directly
+      TransactionAssert.beginTransaction();
+      PropertyMap newCloneValues = new SimplePropertyMap(cloneValues);
+      newCloneValues.setProperty("abc", new StringValue("fed"));
+      persistenceManager.updateState(cloneCtx.getId().substring(1), newCloneValues);
+      TransactionAssert.commitTransaction();
+
+      // Clone the modified CCP
+      TransactionAssert.beginTransaction();
+      PortletContext cloneCloneCtx = producer.createClone(cloneCtx);
+      TransactionAssert.commitTransaction();
+
+      // Check the clone clone state
+      TransactionAssert.beginTransaction();
+      assertTrue(cloneCloneCtx.getId().startsWith("_"));
+      ProducerStateContext cloneCloneState = persistenceManager.loadState(cloneCloneCtx.getId().substring(1));
+      assertNotNull(cloneCloneState);
+      assertEquals(cloneCloneCtx.getId(), "_" + cloneCloneState.getId());
+      assertEquals("SimplePortlet", cloneCloneState.getPortletId());
+      PropertyMap cloneCloneValues = cloneCloneState.getProperties();
+      assertNotNull(cloneCloneValues);
+      assertNotNull(cloneCloneValues.keySet());
+      assertEquals(1, cloneCloneValues.keySet().size());
+      assertEquals(new StringValue("fed"), cloneCloneValues.getProperty("abc"));
+      TransactionAssert.commitTransaction();
+   }
+
+   public void testDestroyNonExistingPortletWithinTx() throws Exception
+   {
+      TransactionAssert.beginTransaction();
+      List failures = producer.destroyClones(Collections.singletonList(new PortletContext("_1")));
+      assertEquals(Collections.singletonList(new DestroyCloneFailure("_1")), failures);
+      TransactionAssert.commitTransaction();
+   }
+
+   public void testDestroyNullPortletWithinTx() throws Exception
+   {
+      try
+      {
+         TransactionAssert.beginTransaction();
+         producer.destroyClones(null);
+         fail("Was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException expected)
+      {
+         TransactionAssert.rollbackTransaction(true);
+      }
+   }
+
+/*
+   public void testDestroyInvalidPortletWithinTx() throws Exception
+   {
+      try
+      {
+         TransactionAssert.beginTransaction();
+         statefulPortletInvoker.destroyClone("_invalid");
+         fail("Was expecting an InvalidPortletIdException");
+      }
+      catch (InvalidPortletIdException expected)
+      {
+         TransactionAssert.rollbackTransaction(true);
+      }
+   }
+*/
+
+   public void testDestroyPortletWithinTx() throws Exception
+   {
+      // Clone a POP 2 times
+      TransactionAssert.beginTransaction();
+      PortletContext cloneId1 = producer.createClone(new PortletContext("SimplePortlet"));
+      PortletContext cloneId2 = producer.createClone(new PortletContext("SimplePortlet"));
+      TransactionAssert.commitTransaction();
+
+      // Clone the modified CCP 2 times
+      TransactionAssert.beginTransaction();
+      PortletContext cloneCloneId1 = producer.createClone(cloneId1);
+      PortletContext cloneCloneId2 = producer.createClone(cloneId1);
+      TransactionAssert.commitTransaction();
+
+      // Destroy the clone 2
+      TransactionAssert.beginTransaction();
+      List failures = producer.destroyClones(Collections.singletonList(cloneId2));
+      assertEquals(Collections.EMPTY_LIST, failures);
+      TransactionAssert.commitTransaction();
+
+      // Destroy the clone of the clone 2
+      TransactionAssert.beginTransaction();
+      failures = producer.destroyClones(Collections.singletonList(cloneCloneId2));
+      assertEquals(Collections.EMPTY_LIST, failures);
+      TransactionAssert.commitTransaction();
+
+      // Destroy the clone 1
+      TransactionAssert.beginTransaction();
+      failures = producer.destroyClones(Collections.singletonList(cloneId1));
+      assertEquals(Collections.EMPTY_LIST, failures);
+      TransactionAssert.commitTransaction();
+
+      // Destroy the clone of the clone 1
+      TransactionAssert.beginTransaction();
+      failures = producer.destroyClones(Collections.singletonList(cloneCloneId1));
+      assertEquals(Collections.EMPTY_LIST, failures);
+      TransactionAssert.commitTransaction();
+   }
+
+   public void testInvokeCloneBeforeWritePOPWithinTx() throws Exception
+   {
+      TransactionAssert.beginTransaction();
+      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
+      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, new PortletContext("CloningPortlet"));
+      action.setUserContext(new SimpleUserContext("julien"));
+      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.CLONE_BEFORE_WRITE);
+      action.setInstanceContext(instanceContext);
+      producer.invoke(action);
+      TransactionAssert.commitTransaction();
+
+      // Check state
+      TransactionAssert.beginTransaction();
+      PortletContext cloneId = instanceContext.getClonedContext();
+      assertNotNull(cloneId);
+      ProducerStateContext state = persistenceManager.loadState(cloneId.getId().substring(1));
+      assertNotNull(state);
+      assertEquals(cloneId.getId().substring(1), state.getId());
+      assertEquals("CloningPortlet", state.getPortletId());
+      SimplePropertyMap expectedValue = new SimplePropertyMap();
+      expectedValue.setProperty("abc", new StringValue("def"));
+      expectedValue.setProperty("_abc", new StringValue("_def"));
+      ValueMapAssert.assertEquals(expectedValue, state.getProperties());
+      TransactionAssert.commitTransaction();
+   }
+
+   public void testInvokeReadWritePOPWithinTx() throws Exception
+   {
+      TransactionAssert.beginTransaction();
+      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
+      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, new PortletContext("CloneFailedCloningPortlet"));
+      action.setUserContext(new SimpleUserContext("julien"));
+      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.READ_WRITE);
+      action.setInstanceContext(instanceContext);
+      producer.invoke(action);
+      TransactionAssert.commitTransaction();
+
+      // Check state
+      TransactionAssert.beginTransaction();
+      assertNull(instanceContext.getClonedContext());
+      TransactionAssert.commitTransaction();
+   }
+
+   public void testInvokeReadOnlyPOPWithinTx() throws Exception
+   {
+      TransactionAssert.beginTransaction();
+      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
+      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, new PortletContext("CloneFailedCloningPortlet"));
+      action.setUserContext(new SimpleUserContext("julien"));
+      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.READ_ONLY);
+      action.setInstanceContext(instanceContext);
+      producer.invoke(action);
+      TransactionAssert.commitTransaction();
+
+      // Check state
+      TransactionAssert.beginTransaction();
+      assertNull(instanceContext.getClonedContext());
+      TransactionAssert.commitTransaction();
+   }
+
+   public void testInvokeCloneBeforeWriteCCPWithinTx() throws Exception
+   {
+      TransactionAssert.beginTransaction();
+      PortletContext cloningPortletId = producer.createClone(new PortletContext("CloningPortlet"));
+      TransactionAssert.commitTransaction();
+
+      // Modify the state of the CCP
+      TransactionAssert.beginTransaction();
+      ProducerState cloningPortletState = persistenceManager.loadState(cloningPortletId.getId().substring(1));
+      SimplePropertyMap newCloningPortletStateValue = new SimplePropertyMap(cloningPortletState.getProperties());
+      newCloningPortletStateValue.setProperty("abc", new StringValue("deff"));
+      persistenceManager.updateState(cloningPortletId.getId().substring(1), newCloningPortletStateValue);
+      TransactionAssert.commitTransaction();
+
+      //
+      TransactionAssert.beginTransaction();
+      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
+      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, cloningPortletId);
+      action.setUserContext(new SimpleUserContext("julien"));
+      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.CLONE_BEFORE_WRITE);
+      action.setInstanceContext(instanceContext);
+      producer.invoke(action);
+      TransactionAssert.commitTransaction();
+
+      // Check state
+      TransactionAssert.beginTransaction();
+      PortletContext cloneId = instanceContext.getClonedContext();
+      assertNotNull(cloneId);
+      ProducerStateContext state = persistenceManager.loadState(cloneId.getId().substring(1));
+      assertNotNull(state);
+      assertEquals(cloneId.getId().substring(1), state.getId());
+      assertEquals("CloningPortlet", state.getPortletId());
+      SimplePropertyMap expectedValue = new SimplePropertyMap();
+      expectedValue.setProperty("abc", new StringValue("deff"));
+      expectedValue.setProperty("_abc", new StringValue("_def"));
+      ValueMapAssert.assertEquals(expectedValue, state.getProperties());
+      TransactionAssert.commitTransaction();
+   }
+
+   public void testInvokeReadWriteCCPWithinTx() throws Exception
+   {
+      TransactionAssert.beginTransaction();
+      PortletContext cloningPortletId = producer.createClone(new PortletContext("CloningPortlet"));
+      TransactionAssert.commitTransaction();
+
+      //
+      TransactionAssert.beginTransaction();
+      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
+      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, cloningPortletId);
+      action.setUserContext(new SimpleUserContext("julien"));
+      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.READ_WRITE);
+      action.setInstanceContext(instanceContext);
+      producer.invoke(action);
+      TransactionAssert.commitTransaction();
+
+      // Check state
+      TransactionAssert.beginTransaction();
+      assertNull(instanceContext.getClonedContext());
+      ProducerStateContext state = persistenceManager.loadState(cloningPortletId.getId().substring(1));
+      assertNotNull(state);
+      assertEquals("CloningPortlet", state.getPortletId());
+      assertEquals(cloningPortletId.getId().substring(1), state.getId());
+      SimplePropertyMap expectedValue = new SimplePropertyMap();
+      expectedValue.setProperty("abc", new StringValue("def"));
+      expectedValue.setProperty("_abc", new StringValue("_def"));
+      ValueMapAssert.assertEquals(expectedValue, state.getProperties());
+      TransactionAssert.commitTransaction();
+   }
+
+   public void testInvokeReadOnlyCCPWithinTx() throws Exception
+   {
+      TransactionAssert.beginTransaction();
+      PortletContext cloneFailedCloningPortletId = producer.createClone(new PortletContext("CloneFailedCloningPortlet"));
+      TransactionAssert.commitTransaction();
+
+      //
+      TransactionAssert.beginTransaction();
+      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
+      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, cloneFailedCloningPortletId);
+      action.setUserContext(new SimpleUserContext("julien"));
+      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.READ_ONLY);
+      action.setInstanceContext(instanceContext);
+      producer.invoke(action);
+      TransactionAssert.commitTransaction();
+
+      // Check state
+      TransactionAssert.beginTransaction();
+      assertNull(instanceContext.getClonedContext());
+      TransactionAssert.commitTransaction();
+   }
+
+   public void testInvokeCloneBeforeWritePOPWithinTxThrowsException() throws Exception
+   {
+      TransactionAssert.beginTransaction();
+      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
+      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, new PortletContext("CloningPortletThrowingRuntimeException"));
+      action.setUserContext(new SimpleUserContext("julien"));
+      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.CLONE_BEFORE_WRITE);
+      action.setInstanceContext(instanceContext);
+      try
+      {
+         producer.invoke(action);
+         fail("Was expecting RuntimeException");
+      }
+      catch (RuntimeException expected)
+      {
+         assertEquals("custom_message", expected.getMessage());
+         TransactionAssert.rollbackTransaction(true);
+      }
+
+      // Check state
+      TransactionAssert.beginTransaction();
+      assertNull(instanceContext.getClonedContext());
+      TransactionAssert.commitTransaction();
+   }
+
+   public void testGetProperties()
+   {
+
+   }
+
+   public void testSetProperties()
+   {
+
+   }
+
+   /**
+    * todo : should check the portlet metadata as well
+    */
+   public void testGetPortlet() throws Exception
+   {
+      // Clone a POP
+      TransactionAssert.beginTransaction();
+      PortletContext cloneId = producer.createClone(new PortletContext("SimplePortlet"));
+      TransactionAssert.commitTransaction();
+
+      //
+      TransactionAssert.beginTransaction();
+      Portlet portlet = producer.getPortlet(cloneId.getId());
+      assertEquals("SimplePortlet", portlet.getId());
+      TransactionAssert.commitTransaction();
+
+      // Clone the modified CCP
+      TransactionAssert.beginTransaction();
+      PortletContext cloneCloneId = producer.createClone(cloneId);
+      TransactionAssert.commitTransaction();
+
+      //
+      TransactionAssert.beginTransaction();
+      portlet = producer.getPortlet(cloneCloneId.getId());
+      assertEquals("SimplePortlet", portlet.getId());
+      TransactionAssert.commitTransaction();
+   }
+
+}


Property changes on: trunk/core/src/main/org/jboss/portal/test/core/state/ProducerTestCase.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Modified: trunk/core/src/main/org/jboss/portal/test/core/state/SimpleInstanceContext.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/test/core/state/SimpleInstanceContext.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/test/core/state/SimpleInstanceContext.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -23,6 +23,10 @@
 
 import org.jboss.portal.portlet.support.spi.InstanceContextSupport;
 import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.state.PortletClonedEvent;
+import org.jboss.portal.portlet.state.PortletModifiedEvent;
+import org.jboss.portal.portlet.PortletContext;
+import org.jboss.portal.portlet.StateEvent;
 
 /**
  * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
@@ -33,7 +37,8 @@
 
    private final String id;
    private final AccessMode accessMode;
-   private String cloneId;
+   private PortletContext clonedContext;
+   private PortletContext modifiedContext;
 
    public SimpleInstanceContext(String id, AccessMode accessMode)
    {
@@ -46,18 +51,32 @@
       return id;
    }
 
-   public void portletCloned(String cloneId)
+   public AccessMode getAccessMode()
    {
-      this.cloneId = cloneId;
+      return accessMode;
    }
 
-   public AccessMode getAccessMode()
+   public void onStateEvent(StateEvent event)
    {
-      return accessMode;
+      if (event instanceof PortletClonedEvent)
+      {
+         PortletClonedEvent pce = (PortletClonedEvent)event;
+         clonedContext = pce.getClonedContext();
+      }
+      else if (event instanceof PortletModifiedEvent)
+      {
+         PortletModifiedEvent pme = (PortletModifiedEvent)event;
+         clonedContext = pme.getModifiedContext();
+      }
    }
 
-   public String getCloneId()
+   public PortletContext getClonedContext()
    {
-      return cloneId;
+      return clonedContext;
    }
+
+   public PortletContext getModifiedContext()
+   {
+      return modifiedContext;
+   }
 }

Deleted: trunk/core/src/main/org/jboss/portal/test/core/state/StatefulPortletInvokerTestCase.java
===================================================================
--- trunk/core/src/main/org/jboss/portal/test/core/state/StatefulPortletInvokerTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/main/org/jboss/portal/test/core/state/StatefulPortletInvokerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,607 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.test.core.state;
-
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.apache.log4j.Appender;
-import org.apache.log4j.ConsoleAppender;
-import org.apache.log4j.SimpleLayout;
-import org.apache.log4j.Logger;
-import org.apache.log4j.Level;
-import org.jboss.portal.test.framework.embedded.DataSourceSupport;
-import org.jboss.portal.test.framework.embedded.HibernateSupport;
-import org.jboss.portal.test.framework.junit.DatabaseTestSuite;
-import org.jboss.portal.test.framework.junit.TransactionAssert;
-import org.jboss.portal.test.framework.TestRuntimeContext;
-import org.jboss.portal.test.core.model.instance.SimpleActionContext;
-import org.jboss.portal.test.core.model.instance.SimpleUserContext;
-import org.jboss.portal.portlet.test.ValueMapAssert;
-import org.jboss.portal.core.impl.portlet.state.PersistentStateStore;
-import org.jboss.portal.core.impl.portlet.state.StatefulPortletInvoker;
-import org.jboss.portal.portlet.NoSuchPortletException;
-import org.jboss.portal.portlet.Portlet;
-import org.jboss.portal.Mode;
-import org.jboss.portal.portlet.invocation.PortletInvocation;
-import org.jboss.portal.portlet.invocation.ActionInvocation;
-import org.jboss.portal.portlet.state.producer.State;
-import org.jboss.portal.portlet.state.AbstractPropertyContext;
-import org.jboss.portal.portlet.state.PropertyChange;
-import org.jboss.portal.portlet.state.AccessMode;
-import org.jboss.portal.portlet.state.PropertyMap;
-import org.jboss.portal.portlet.state.SimplePropertyMap;
-import org.jboss.portal.portlet.state.DestroyCloneFailure;
-import org.jboss.portal.portlet.test.support.info.PreferencesInfoSupport;
-import org.jboss.portal.portlet.test.support.PortletInvokerSupport;
-import org.jboss.portal.portlet.test.support.PortletSupport;
-import org.jboss.portal.common.value.StringValue;
-
-import java.net.URL;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public class StatefulPortletInvokerTestCase extends TestCase
-{
-
-   static
-   {
-      Appender appender = new ConsoleAppender(new SimpleLayout());
-      Logger.getRoot().addAppender(appender);
-      Logger.getRoot().setLevel(Level.DEBUG);
-      Logger.getLogger("org.hibernate").setLevel(Level.ERROR);
-   }
-
-   public static TestSuite suite() throws Exception
-   {
-      URL configsURL = Thread.currentThread().getContextClassLoader().getResource("datasources.xml");
-      DataSourceSupport.Config[] configs = DataSourceSupport.Config.fromXML(configsURL);
-      DatabaseTestSuite suite = new DatabaseTestSuite(configs);
-      suite.addTestCase(StatefulPortletInvokerTestCase.class);
-      return suite;
-   }
-
-   /** . */
-   private TestRuntimeContext runtimeContext;
-
-   /** . */
-   private DataSourceSupport.Config dsCfg;
-
-   /** . */
-   private HibernateSupport hibernateSupport;
-
-   /** . */
-   private PersistentStateStore stateStore;
-
-   /** . */
-   private StatefulPortletInvoker statefulPortletInvoker;
-
-   /** . */
-   private PortletInvokerSupport nextPortletInvoker;
-
-   public StatefulPortletInvokerTestCase(DataSourceSupport.Config config)
-   {
-      this.dsCfg = config;
-   }
-
-   public HibernateSupport getHibernateSupport()
-   {
-      return hibernateSupport;
-   }
-
-   public void setHibernateSupport(HibernateSupport hibernateSupport)
-   {
-      this.hibernateSupport = hibernateSupport;
-   }
-
-   public PersistentStateStore getStateStore()
-   {
-      return stateStore;
-   }
-
-   public void setStateStore(PersistentStateStore stateStore)
-   {
-      this.stateStore = stateStore;
-   }
-
-   public StatefulPortletInvoker getStatefulPortletInvoker()
-   {
-      return statefulPortletInvoker;
-   }
-
-   public void setStatefulPortletInvoker(StatefulPortletInvoker statefulPortletInvoker)
-   {
-      this.statefulPortletInvoker = statefulPortletInvoker;
-   }
-
-   public PortletInvokerSupport getNextPortletInvoker()
-   {
-      return nextPortletInvoker;
-   }
-
-   public void setNextPortletInvoker(PortletInvokerSupport nextPortletInvoker)
-   {
-      this.nextPortletInvoker = nextPortletInvoker;
-   }
-
-   protected void setUp() throws Exception
-   {
-      runtimeContext = new TestRuntimeContext("org/jboss/portal/test/core/state/jboss-beans.xml");
-      runtimeContext.addBean("TestBean", this);
-      runtimeContext.addBean("DataSourceConfig", dsCfg);
-      runtimeContext.start();
-
-      nextPortletInvoker.addPortlet(new PortletSupport("SimplePortlet")
-      {
-         {
-            PreferencesInfoSupport prefs = info.getPreferencesSupport();
-            prefs.addPreference("abc", new StringValue("def"));
-         }
-         public void invoke(PortletInvocation invocation)
-         {
-            AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
-            props.update(new PropertyChange[]{PropertyChange.newUpdate("_abc", new StringValue("_def"))});
-         }
-      });
-
-      nextPortletInvoker.addPortlet(new PortletSupport("CloningPortlet")
-      {
-         {
-            PreferencesInfoSupport prefs = info.getPreferencesSupport();
-            prefs.addPreference("abc", new StringValue("def"));
-         }
-         public void invoke(PortletInvocation invocation)
-         {
-            AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
-            props.update(new PropertyChange[]{PropertyChange.newUpdate("_abc", new StringValue("_def"))});
-         }
-      });
-
-      nextPortletInvoker.addPortlet(new PortletSupport("CloneFailedCloningPortlet")
-      {
-         {
-            PreferencesInfoSupport prefs = info.getPreferencesSupport();
-            prefs.addPreference("abc", new StringValue("def"));
-         }
-         public void invoke(PortletInvocation invocation)
-         {
-            try
-            {
-               AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
-               props.update(new PropertyChange[]{PropertyChange.newUpdate("_abc", new StringValue("_def"))});
-               fail("Was expecting an IllegalStateException");
-            }
-            catch (IllegalStateException expected)
-            {
-            }
-         }
-      });
-
-      nextPortletInvoker.addPortlet(new PortletSupport("CloningPortletThrowingRuntimeException")
-      {
-         {
-            PreferencesInfoSupport prefs = info.getPreferencesSupport();
-            prefs.addPreference("abc", new StringValue("def"));
-         }
-         public void invoke(PortletInvocation invocation)
-         {
-            AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
-            props.update(new PropertyChange[]{PropertyChange.newUpdate("_abc", new StringValue("_def"))});
-            throw new RuntimeException("custom_message");
-         }
-      });
-   }
-
-   protected void tearDown() throws Exception
-   {
-      // Cleanup any pending transaction
-      TransactionAssert.endTransaction();
-
-      runtimeContext.stop();
-   }
-
-   public void testCloneNonExistingPortletWithinTx() throws Exception
-   {
-      try
-      {
-         TransactionAssert.beginTransaction();
-         statefulPortletInvoker.createClone("UnknownPortlet");
-         fail("Was expecting no such portlet exception");
-      }
-      catch (NoSuchPortletException e)
-      {
-         TransactionAssert.rollbackTransaction(true);
-      }
-
-      // todo check state
-
-//      try
-//      {
-//         TransactionAssert.beginTransaction();
-//         statefulPortletInvoker.createClone("_1");
-//         fail("Was expecting no such portlet exception");
-//      }
-//      catch (NoSuchPortletException e)
-//      {
-//         TransactionAssert.rollbackTransaction(true);
-//      }
-
-      // todo check state
-   }
-
-   public void testCloneNullPortletWithinTx() throws Exception
-   {
-      try
-      {
-         TransactionAssert.beginTransaction();
-         statefulPortletInvoker.createClone(null);
-         fail("Was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException expected)
-      {
-         TransactionAssert.rollbackTransaction(true);
-      }
-   }
-
-   public void testCloneExistingPortletWithinTx() throws Exception
-   {
-      // Clone a POP
-      TransactionAssert.beginTransaction();
-      String cloneId = statefulPortletInvoker.createClone("SimplePortlet");
-      TransactionAssert.commitTransaction();
-
-      // Check the clone state
-      TransactionAssert.beginTransaction();
-      assertTrue(cloneId.startsWith("_"));
-      State cloneState = stateStore.loadState(cloneId.substring(1));
-      assertNotNull(cloneState);
-      assertEquals(cloneId, "_" + cloneState.getId());
-      assertEquals("SimplePortlet", cloneState.getPortletId());
-      PropertyMap cloneValues = cloneState.getProperties();
-      assertNotNull(cloneValues);
-      assertNotNull(cloneValues.keySet());
-      assertEquals(1, cloneValues.keySet().size());
-      assertEquals(new StringValue("def"), cloneValues.getProperty("abc"));
-      TransactionAssert.commitTransaction();
-
-      // Update CCP state directly
-      TransactionAssert.beginTransaction();
-      PropertyMap newCloneValues = new SimplePropertyMap(cloneValues);
-      newCloneValues.setProperty("abc", new StringValue("fed"));
-      stateStore.updateState(cloneId.substring(1), newCloneValues);
-      TransactionAssert.commitTransaction();
-
-      // Clone the modified CCP
-      TransactionAssert.beginTransaction();
-      String cloneCloneId = statefulPortletInvoker.createClone(cloneId);
-      TransactionAssert.commitTransaction();
-
-      // Check the clone clone state
-      TransactionAssert.beginTransaction();
-      assertTrue(cloneCloneId.startsWith("_"));
-      State cloneCloneState = stateStore.loadState(cloneCloneId.substring(1));
-      assertNotNull(cloneCloneState);
-      assertEquals(cloneCloneId, "_" + cloneCloneState.getId());
-      assertEquals("SimplePortlet", cloneCloneState.getPortletId());
-      PropertyMap cloneCloneValues = cloneCloneState.getProperties();
-      assertNotNull(cloneCloneValues);
-      assertNotNull(cloneCloneValues.keySet());
-      assertEquals(1, cloneCloneValues.keySet().size());
-      assertEquals(new StringValue("fed"), cloneCloneValues.getProperty("abc"));
-      TransactionAssert.commitTransaction();
-   }
-
-   public void testDestroyNonExistingPortletWithinTx() throws Exception
-   {
-      TransactionAssert.beginTransaction();
-      List failures = statefulPortletInvoker.destroyClones(Collections.singletonList("_1"));
-      assertEquals(Collections.singletonList(new DestroyCloneFailure("_1")), failures);
-      TransactionAssert.commitTransaction();
-   }
-
-   public void testDestroyNullPortletWithinTx() throws Exception
-   {
-      try
-      {
-         TransactionAssert.beginTransaction();
-         statefulPortletInvoker.destroyClones(null);
-         fail("Was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException expected)
-      {
-         TransactionAssert.rollbackTransaction(true);
-      }
-   }
-
-/*
-   public void testDestroyInvalidPortletWithinTx() throws Exception
-   {
-      try
-      {
-         TransactionAssert.beginTransaction();
-         statefulPortletInvoker.destroyClone("_invalid");
-         fail("Was expecting an InvalidPortletIdException");
-      }
-      catch (InvalidPortletIdException expected)
-      {
-         TransactionAssert.rollbackTransaction(true);
-      }
-   }
-*/
-
-   public void testDestroyPortletWithinTx() throws Exception
-   {
-      // Clone a POP 2 times
-      TransactionAssert.beginTransaction();
-      String cloneId1 = statefulPortletInvoker.createClone("SimplePortlet");
-      String cloneId2 = statefulPortletInvoker.createClone("SimplePortlet");
-      TransactionAssert.commitTransaction();
-
-      // Clone the modified CCP 2 times
-      TransactionAssert.beginTransaction();
-      String cloneCloneId1 = statefulPortletInvoker.createClone(cloneId1);
-      String cloneCloneId2 = statefulPortletInvoker.createClone(cloneId1);
-      TransactionAssert.commitTransaction();
-
-      // Destroy the clone 2
-      TransactionAssert.beginTransaction();
-      List failures = statefulPortletInvoker.destroyClones(Collections.singletonList(cloneId2));
-      assertEquals(Collections.EMPTY_LIST, failures);
-      TransactionAssert.commitTransaction();
-
-      // Destroy the clone of the clone 2
-      TransactionAssert.beginTransaction();
-      failures = statefulPortletInvoker.destroyClones(Collections.singletonList(cloneCloneId2));
-      assertEquals(Collections.EMPTY_LIST, failures);
-      TransactionAssert.commitTransaction();
-
-      // Destroy the clone 1
-      TransactionAssert.beginTransaction();
-      failures = statefulPortletInvoker.destroyClones(Collections.singletonList(cloneId1));
-      assertEquals(Collections.EMPTY_LIST, failures);
-      TransactionAssert.commitTransaction();
-
-      // Destroy the clone of the clone 1
-      TransactionAssert.beginTransaction();
-      failures = statefulPortletInvoker.destroyClones(Collections.singletonList(cloneCloneId1));
-      assertEquals(Collections.EMPTY_LIST, failures);
-      TransactionAssert.commitTransaction();
-   }
-
-   public void testInvokeCloneBeforeWritePOPWithinTx() throws Exception
-   {
-      TransactionAssert.beginTransaction();
-      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
-      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, "CloningPortlet");
-      action.setUserContext(new SimpleUserContext("julien"));
-      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.CLONE_BEFORE_WRITE);
-      action.setInstanceContext(instanceContext);
-      statefulPortletInvoker.invoke(action);
-      TransactionAssert.commitTransaction();
-
-      // Check state
-      TransactionAssert.beginTransaction();
-      String cloneId = instanceContext.getCloneId();
-      assertNotNull(cloneId);
-      State state = stateStore.loadState(cloneId.substring(1));
-      assertNotNull(state);
-      assertEquals(cloneId.substring(1), state.getId());
-      assertEquals("CloningPortlet", state.getPortletId());
-      SimplePropertyMap expectedValue = new SimplePropertyMap();
-      expectedValue.setProperty("abc", new StringValue("def"));
-      expectedValue.setProperty("_abc", new StringValue("_def"));
-      ValueMapAssert.assertEquals(expectedValue, state.getProperties());
-      TransactionAssert.commitTransaction();
-   }
-
-   public void testInvokeReadWritePOPWithinTx() throws Exception
-   {
-      TransactionAssert.beginTransaction();
-      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
-      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, "CloneFailedCloningPortlet");
-      action.setUserContext(new SimpleUserContext("julien"));
-      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.READ_WRITE);
-      action.setInstanceContext(instanceContext);
-      statefulPortletInvoker.invoke(action);
-      TransactionAssert.commitTransaction();
-
-      // Check state
-      TransactionAssert.beginTransaction();
-      assertNull(instanceContext.getCloneId());
-      TransactionAssert.commitTransaction();
-   }
-
-   public void testInvokeReadOnlyPOPWithinTx() throws Exception
-   {
-      TransactionAssert.beginTransaction();
-      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
-      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, "CloneFailedCloningPortlet");
-      action.setUserContext(new SimpleUserContext("julien"));
-      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.READ_ONLY);
-      action.setInstanceContext(instanceContext);
-      statefulPortletInvoker.invoke(action);
-      TransactionAssert.commitTransaction();
-
-      // Check state
-      TransactionAssert.beginTransaction();
-      assertNull(instanceContext.getCloneId());
-      TransactionAssert.commitTransaction();
-   }
-
-   public void testInvokeCloneBeforeWriteCCPWithinTx() throws Exception
-   {
-      TransactionAssert.beginTransaction();
-      String cloningPortletId = statefulPortletInvoker.createClone("CloningPortlet");
-      TransactionAssert.commitTransaction();
-
-      // Modify the state of the CCP
-      TransactionAssert.beginTransaction();
-      State cloningPortletState = stateStore.loadState(cloningPortletId.substring(1));
-      SimplePropertyMap newCloningPortletStateValue = new SimplePropertyMap(cloningPortletState.getProperties());
-      newCloningPortletStateValue.setProperty("abc", new StringValue("deff"));
-      stateStore.updateState(cloningPortletId.substring(1), newCloningPortletStateValue);
-      TransactionAssert.commitTransaction();
-
-      //
-      TransactionAssert.beginTransaction();
-      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
-      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, cloningPortletId);
-      action.setUserContext(new SimpleUserContext("julien"));
-      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.CLONE_BEFORE_WRITE);
-      action.setInstanceContext(instanceContext);
-      statefulPortletInvoker.invoke(action);
-      TransactionAssert.commitTransaction();
-
-      // Check state
-      TransactionAssert.beginTransaction();
-      String cloneId = instanceContext.getCloneId();
-      assertNotNull(cloneId);
-      State state = stateStore.loadState(cloneId.substring(1));
-      assertNotNull(state);
-      assertEquals(cloneId.substring(1), state.getId());
-      assertEquals("CloningPortlet", state.getPortletId());
-      SimplePropertyMap expectedValue = new SimplePropertyMap();
-      expectedValue.setProperty("abc", new StringValue("deff"));
-      expectedValue.setProperty("_abc", new StringValue("_def"));
-      ValueMapAssert.assertEquals(expectedValue, state.getProperties());
-      TransactionAssert.commitTransaction();
-   }
-
-   public void testInvokeReadWriteCCPWithinTx() throws Exception
-   {
-      TransactionAssert.beginTransaction();
-      String cloningPortletId = statefulPortletInvoker.createClone("CloningPortlet");
-      TransactionAssert.commitTransaction();
-
-      //
-      TransactionAssert.beginTransaction();
-      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
-      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, cloningPortletId);
-      action.setUserContext(new SimpleUserContext("julien"));
-      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.READ_WRITE);
-      action.setInstanceContext(instanceContext);
-      statefulPortletInvoker.invoke(action);
-      TransactionAssert.commitTransaction();
-
-      // Check state
-      TransactionAssert.beginTransaction();
-      assertNull(instanceContext.getCloneId());
-      State state = stateStore.loadState(cloningPortletId.substring(1));
-      assertNotNull(state);
-      assertEquals("CloningPortlet", state.getPortletId());
-      assertEquals(cloningPortletId.substring(1), state.getId());
-      SimplePropertyMap expectedValue = new SimplePropertyMap();
-      expectedValue.setProperty("abc", new StringValue("def"));
-      expectedValue.setProperty("_abc", new StringValue("_def"));
-      ValueMapAssert.assertEquals(expectedValue, state.getProperties());
-      TransactionAssert.commitTransaction();
-   }
-
-   public void testInvokeReadOnlyCCPWithinTx() throws Exception
-   {
-      TransactionAssert.beginTransaction();
-      String cloneFailedCloningPortletId = statefulPortletInvoker.createClone("CloneFailedCloningPortlet");
-      TransactionAssert.commitTransaction();
-
-      //
-      TransactionAssert.beginTransaction();
-      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
-      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, cloneFailedCloningPortletId);
-      action.setUserContext(new SimpleUserContext("julien"));
-      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.READ_ONLY);
-      action.setInstanceContext(instanceContext);
-      statefulPortletInvoker.invoke(action);
-      TransactionAssert.commitTransaction();
-
-      // Check state
-      TransactionAssert.beginTransaction();
-      assertNull(instanceContext.getCloneId());
-      TransactionAssert.commitTransaction();
-   }
-
-   public void testInvokeCloneBeforeWritePOPWithinTxThrowsException() throws Exception
-   {
-      TransactionAssert.beginTransaction();
-      PortletInvocation action = new ActionInvocation(new SimpleActionContext(Mode.VIEW));
-      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, "CloningPortletThrowingRuntimeException");
-      action.setUserContext(new SimpleUserContext("julien"));
-      SimpleInstanceContext instanceContext = new SimpleInstanceContext("whatever", AccessMode.CLONE_BEFORE_WRITE);
-      action.setInstanceContext(instanceContext);
-      try
-      {
-         statefulPortletInvoker.invoke(action);
-         fail("Was expecting RuntimeException");
-      }
-      catch (RuntimeException expected)
-      {
-         assertEquals("custom_message", expected.getMessage());
-         TransactionAssert.rollbackTransaction(true);
-      }
-
-      // Check state
-      TransactionAssert.beginTransaction();
-      assertNull(instanceContext.getCloneId());
-      TransactionAssert.commitTransaction();
-   }
-
-   public void testGetProperties()
-   {
-
-   }
-
-   public void testSetProperties()
-   {
-
-   }
-
-   /**
-    * todo : should check the portlet metadata as well
-    */
-   public void testGetPortlet() throws Exception
-   {
-      // Clone a POP
-      TransactionAssert.beginTransaction();
-      String cloneId = statefulPortletInvoker.createClone("SimplePortlet");
-      TransactionAssert.commitTransaction();
-
-      //
-      TransactionAssert.beginTransaction();
-      Portlet portlet = statefulPortletInvoker.getPortlet(cloneId);
-      assertEquals("SimplePortlet", portlet.getId());
-      TransactionAssert.commitTransaction();
-
-      // Clone the modified CCP
-      TransactionAssert.beginTransaction();
-      String cloneCloneId = statefulPortletInvoker.createClone(cloneId);
-      TransactionAssert.commitTransaction();
-
-      //
-      TransactionAssert.beginTransaction();
-      portlet = statefulPortletInvoker.getPortlet(cloneCloneId);
-      assertEquals("SimplePortlet", portlet.getId());
-      TransactionAssert.commitTransaction();
-   }
-
-}

Modified: trunk/core/src/resources/portal-core-sar/META-INF/jboss-service.xml
===================================================================
--- trunk/core/src/resources/portal-core-sar/META-INF/jboss-service.xml	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/resources/portal-core-sar/META-INF/jboss-service.xml	2006-09-12 16:51:45 UTC (rev 5180)
@@ -43,17 +43,6 @@
          proxy-type="attribute">portal:service=AuthorizationDomainRegistry</depends>
    </mbean>
 
-   <!-- Portlet state -->
-   <mbean
-      code="org.jboss.portal.core.impl.portlet.state.PersistentStateStore"
-      name="portal:service=StateStore,type=Producer"
-      xmbean-dd=""
-      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
-      <xmbean/>
-      <depends>portal:service=Hibernate,type=Portlet</depends>
-      <attribute name="SessionFactoryJNDIName">java:/portal/PortletSessionFactory</attribute>
-   </mbean>
-
    <!-- Server stack -->
    <mbean
       code="org.jboss.portal.core.aspects.server.TransactionInterceptor"
@@ -494,8 +483,11 @@
       <xmbean/>
       <depends>portal:service=Hibernate,type=Instance</depends>
       <depends
+         optional-attribute-name="StackFactory"
+         proxy-type="attribute">portal:service=InterceptorStackFactory,type=Instance</depends>
+      <depends
          optional-attribute-name="PortletInvoker"
-         proxy-type="attribute">portal:service=PortletInvoker,type=Instance</depends>
+         proxy-type="attribute">portal:service=PortletInvoker,type=Federating</depends>
       <depends
          optional-attribute-name="PortalAuthorizationManagerFactory"
          proxy-type="attribute">portal:service=PortalAuthorizationManagerFactory</depends>
@@ -613,19 +605,49 @@
          proxy-type="attribute">portal:service=WebAppRegistry</depends>
    </mbean>
 
-   <!-- The state portlet invoker -->
+   <!-- The producer portlet invoker -->
    <mbean
-      code="org.jboss.portal.portlet.state.producer.StatefulPortletInvoker"
-      name="portal:service=PortletInvoker,type=Stateful"
+      code="org.jboss.portal.core.impl.portlet.state.PersistentStateStore"
+      name="portal:service=PersistenceManager,type=Producer"
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
       <xmbean/>
+      <depends>portal:service=Hibernate,type=Portlet</depends>
+      <attribute name="SessionFactoryJNDIName">java:/portal/PortletSessionFactory</attribute>
+   </mbean>
+   <mbean
+      code="org.jboss.portal.portlet.impl.state.StateManagementPolicyService"
+      name="portal:service=StateManagementPolicy,type=Producer"
+      xmbean-dd=""
+      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
+      <xmbean/>
+      <attribute name="PersistLocally">true</attribute>
+   </mbean>
+   <mbean
+      code="org.jboss.portal.portlet.impl.state.StateConverterService"
+      name="portal:service=StateConverter,type=Producer"
+      xmbean-dd=""
+      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
+      <xmbean/>
+   </mbean>
+   <mbean
+      code="org.jboss.portal.core.impl.portlet.state.ProducerPortletInvoker"
+      name="portal:service=PortletInvoker,type=Producer"
+      xmbean-dd=""
+      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
+      <xmbean/>
       <depends
          optional-attribute-name="PortletInvoker"
          proxy-type="attribute">portal:service=PortletInvoker,type=Container</depends>
       <depends
-         optional-attribute-name="StateStore"
-         proxy-type="attribute">portal:service=StateStore,type=Producer</depends>
+         optional-attribute-name="PersistenceManager"
+         proxy-type="attribute">portal:service=PersistenceManager,type=Producer</depends>
+      <depends
+         optional-attribute-name="StateManagementPolicy"
+         proxy-type="attribute">portal:service=StateManagementPolicy,type=Producer</depends>
+      <depends
+         optional-attribute-name="StateConverter"
+         proxy-type="attribute">portal:service=StateConverter,type=Producer</depends>
    </mbean>
 
    <!-- Register the state portlet invoker on the federating portlet invoker -->
@@ -638,28 +660,12 @@
       <attribute name="Id">local</attribute>
       <depends
          optional-attribute-name="PortletInvoker"
-         proxy-type="attribute">portal:service=PortletInvoker,type=Stateful</depends>
+         proxy-type="attribute">portal:service=PortletInvoker,type=Producer</depends>
       <depends
          optional-attribute-name="FederatingPortletInvoker"
          proxy-type="attribute">portal:service=PortletInvoker,type=Federating</depends>
    </mbean>
 
-   <!-- The instance portlet invoker -->
-   <mbean
-      code="org.jboss.portal.portlet.test.TestPortletInvoker"
-      name="portal:service=PortletInvoker,type=Instance"
-      xmbean-dd=""
-      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
-      <xmbean/>
-      <depends
-         optional-attribute-name="Producer"
-         proxy-type="attribute">portal:service=PortletInvoker,type=Federating</depends>
-      <depends
-         optional-attribute-name="StackFactory"
-         proxy-type="attribute">portal:service=InterceptorStackFactory,type=Instance</depends>
-   </mbean>
-
-
    <!-- The core controller -->
    <mbean
       code="org.jboss.portal.core.controller.CoreController"

Modified: trunk/core/src/resources/portal-core-sar/portal-aop.xml
===================================================================
--- trunk/core/src/resources/portal-core-sar/portal-aop.xml	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/resources/portal-core-sar/portal-aop.xml	2006-09-12 16:51:45 UTC (rev 5180)
@@ -88,7 +88,7 @@
    </metadata>
    <metadata
       tag="transaction"
-      class="org.jboss.portal.core.impl.portlet.state.StatefulPortletInvoker">
+      class="org.jboss.portal.core.impl.portlet.state.ProducerPortletInvoker">
       <method name="createClone">
          <trans-attribute>Required</trans-attribute>
       </method>

Modified: trunk/core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/model/instance/jboss-beans.xml
===================================================================
--- trunk/core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/model/instance/jboss-beans.xml	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/model/instance/jboss-beans.xml	2006-09-12 16:51:45 UTC (rev 5180)
@@ -48,22 +48,30 @@
       <property name="jNDIName">java:/PortletSessionFactory</property>
    </bean>
 
-   <bean name="StateStore" class="org.jboss.portal.core.impl.portlet.state.PersistentStateStore">
+   <bean name="StateConverter" class="org.jboss.portal.portlet.impl.state.StateConverterService">
+   </bean>
+   <bean name="StateManagementPolicy" class="org.jboss.portal.portlet.impl.state.StateManagementPolicyService">
+      <property name="persistLocally">true</property>
+   </bean>
+   <bean name="PersistenceManager" class="org.jboss.portal.core.impl.portlet.state.PersistentStateStore">
       <property name="sessionFactoryJNDIName">java:/PortletSessionFactory</property>
    </bean>
-
-   <bean name="NextPortletInvoker" class="org.jboss.portal.portlet.test.support.PortletInvokerSupport">
+   <bean name="PortletContainer" class="org.jboss.portal.portlet.test.support.PortletInvokerSupport">
    </bean>
+   <bean name="Producer" class="org.jboss.portal.portlet.state.producer.ProducerPortletInvoker">
+      <property name="persistenceManager"><inject bean="PersistenceManager"/></property>
+      <property name="portletInvoker"><inject bean="PortletContainer"/></property>
+      <property name="stateManagementPolicy"><inject bean="StateManagementPolicy"/></property>
+      <property name="stateConverter"><inject bean="StateConverter"/></property>
+   </bean>
 
-   <bean name="StatefulPortletInvoker" class="org.jboss.portal.portlet.state.producer.StatefulPortletInvoker">
-      <property name="stateStore"><inject bean="StateStore"/></property>
-      <property name="portletInvoker"><inject bean="NextPortletInvoker"/></property>
+   <bean name="StackFactory" class="org.jboss.portal.common.invocation.EmptyInterceptorStackFactory">
    </bean>
-
    <bean name="InstanceContainer" class="org.jboss.portal.core.impl.model.instance.PersistentInstanceContainer">
       <property name="cloneOnCreate">false</property>
-      <property name="portletInvoker"><inject bean="StatefulPortletInvoker"/></property>
+      <property name="portletInvoker"><inject bean="Producer"/></property>
       <property name="sessionFactoryJNDIName">java:/InstanceSessionFactory</property>
+      <property name="stackFactory"><inject bean="StackFactory"/></property>
    </bean>
 
    <bean name="TestBean" class="org.jboss.portal.test.core.model.instance.InstanceContainerTestCase">
@@ -74,8 +82,8 @@
       <property name="instanceHibernateSupport"><inject bean="InstanceHibernateSupport"/></property>
       <property name="portletHibernateSupport"><inject bean="PortletHibernateSupport"/></property>
       <property name="instanceContainer"><inject bean="InstanceContainer"/></property>
-      <property name="stateStore"><inject bean="StateStore"/></property>
-      <property name="statefulPortletInvoker"><inject bean="StatefulPortletInvoker"/></property>
-      <property name="nextPortletInvoker"><inject bean="NextPortletInvoker"/></property>
+      <property name="persistenceManager"><inject bean="PersistenceManager"/></property>
+      <property name="producer"><inject bean="Producer"/></property>
+      <property name="portletContainer"><inject bean="PortletContainer"/></property>
    </bean>
 </deployment>

Modified: trunk/core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/state/jboss-beans.xml
===================================================================
--- trunk/core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/state/jboss-beans.xml	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/core/src/resources/portal-core-test-jar/org/jboss/portal/test/core/state/jboss-beans.xml	2006-09-12 16:51:45 UTC (rev 5180)
@@ -39,26 +39,35 @@
       <property name="jNDIName">java:/SessionFactory</property>
    </bean>
 
-   <bean name="StateStore" class="org.jboss.portal.core.impl.portlet.state.PersistentStateStore">
+   <bean name="StateConverter" class="org.jboss.portal.portlet.impl.state.StateConverterService">
+   </bean>
+
+   <bean name="StateManagementPolicy" class="org.jboss.portal.portlet.impl.state.StateManagementPolicyService">
+      <property name="persistLocally">true</property>
+   </bean>
+
+   <bean name="PersistenceManager" class="org.jboss.portal.core.impl.portlet.state.PersistentStateStore">
       <property name="sessionFactoryJNDIName">java:/SessionFactory</property>
    </bean>
 
-   <bean name="NextPortletInvoker" class="org.jboss.portal.portlet.test.support.PortletInvokerSupport">
+   <bean name="PortletContainer" class="org.jboss.portal.portlet.test.support.PortletInvokerSupport">
    </bean>
 
-   <bean name="StatefulPortletInvoker" class="org.jboss.portal.core.impl.portlet.state.StatefulPortletInvoker">
-      <property name="stateStore"><inject bean="StateStore"/></property>
-      <property name="portletInvoker"><inject bean="NextPortletInvoker"/></property>
+   <bean name="Producer" class="org.jboss.portal.core.impl.portlet.state.ProducerPortletInvoker">
+      <property name="persistenceManager"><inject bean="PersistenceManager"/></property>
+      <property name="portletInvoker"><inject bean="PortletContainer"/></property>
+      <property name="stateManagementPolicy"><inject bean="StateManagementPolicy"/></property>
+      <property name="stateConverter"><inject bean="StateConverter"/></property>
    </bean>
 
-   <bean name="TestBean" class="org.jboss.portal.test.core.state.StatefulPortletInvokerTestCase">
+   <bean name="TestBean" class="org.jboss.portal.test.core.state.ProducerTestCase">
       <constructor factoryMethod="getBean">
          <factory bean="BeanFactory"/>
          <parameter>TestBean</parameter>
       </constructor>
       <property name="hibernateSupport"><inject bean="HibernateSupport"/></property>
-      <property name="stateStore"><inject bean="StateStore"/></property>
-      <property name="statefulPortletInvoker"><inject bean="StatefulPortletInvoker"/></property>
-      <property name="nextPortletInvoker"><inject bean="NextPortletInvoker"/></property>
+      <property name="persistenceManager"><inject bean="PersistenceManager"/></property>
+      <property name="producer"><inject bean="Producer"/></property>
+      <property name="portletContainer"><inject bean="PortletContainer"/></property>
    </bean>
 </deployment>

Modified: trunk/federation/src/main/org/jboss/portal/federation/impl/FederatedPortletInvokerService.java
===================================================================
--- trunk/federation/src/main/org/jboss/portal/federation/impl/FederatedPortletInvokerService.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/federation/src/main/org/jboss/portal/federation/impl/FederatedPortletInvokerService.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -29,8 +29,13 @@
 import org.jboss.portal.portlet.Portlet;
 import org.jboss.portal.portlet.PortletInvoker;
 import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.StateEvent;
+import org.jboss.portal.portlet.PortletContext;
 import org.jboss.portal.portlet.state.AccessMode;
 import org.jboss.portal.portlet.state.PropertyChange;
+import org.jboss.portal.portlet.state.PortletClonedEvent;
+import org.jboss.portal.portlet.state.PortletModifiedEvent;
+import org.jboss.portal.portlet.state.DestroyCloneFailure;
 import org.jboss.portal.portlet.spi.InstanceContext;
 import org.jboss.portal.portlet.invocation.PortletInvocation;
 
@@ -81,7 +86,7 @@
       for (Iterator i = portletInvoker.getPortlets().iterator(); i.hasNext();)
       {
          Portlet portlet = (Portlet)i.next();
-         Portlet federatedPortlet = new FederatedPortlet(id + FederatingPortletInvokerService.SEPARATOR + portlet.getId(), portlet);
+         Portlet federatedPortlet = new FederatedPortlet(reference(portlet.getId()), portlet);
          federatedPortlets.add(federatedPortlet);
       }
       return federatedPortlets;
@@ -90,7 +95,7 @@
    public Portlet getPortlet(String compoundPortletId) throws IllegalArgumentException, PortletInvokerException
    {
       // Get portlet id
-      String portletId = getPortletIdFrom(compoundPortletId);
+      String portletId = dereference(compoundPortletId);
 
       // Retrieve wrapped portlet
       Portlet portlet = portletInvoker.getPortlet(portletId);
@@ -115,44 +120,51 @@
          return ctx.getId();
       }
 
-      public void portletCloned(String cloneId)
+      public AccessMode getAccessMode()
       {
-         ctx.portletCloned(id + "." + cloneId);
+         return ctx.getAccessMode();
       }
 
-      public void portletCloned(byte[] state)
+      public void onStateEvent(StateEvent event)
       {
-         ctx.portletCloned(state);
+         if (event instanceof PortletClonedEvent)
+         {
+            PortletClonedEvent pce = (PortletClonedEvent)event;
+            PortletContext clonedContext = pce.getClonedContext();
+            ctx.onStateEvent(new PortletClonedEvent(reference(clonedContext)));
+         }
+         else if (event instanceof PortletModifiedEvent)
+         {
+            PortletModifiedEvent pce = (PortletModifiedEvent)event;
+            PortletContext modifiedContext = pce.getModifiedContext();
+            ctx.onStateEvent(new PortletModifiedEvent(reference(modifiedContext)));
+         }
       }
-
-      public AccessMode getAccessMode()
-      {
-         return ctx.getAccessMode();
-      }
    }
 
    public void invoke(PortletInvocation invocation) throws InvocationException, PortletInvokerException
    {
-      String compoundPortletId = (String)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE);
-      String portletId = getPortletIdFrom(compoundPortletId);
+      PortletContext compoundPortletContext = (PortletContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE);
+      PortletContext portletContext = dereference(compoundPortletContext);
       InstanceContext instanceContext = invocation.getInstanceContext();
       try
       {
-         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, portletId);
+         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, portletContext);
          invocation.setInstanceContext(new FederatedInstanceContext(instanceContext));
          portletInvoker.invoke(invocation);
       }
       finally
       {
-         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, compoundPortletId);
+         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, compoundPortletContext);
          invocation.setInstanceContext(instanceContext);
       }
    }
 
-   public String createClone(String compoundPortletId) throws PortletInvokerException
+   public PortletContext createClone(PortletContext compoundPortletContext) throws PortletInvokerException
    {
-      String portletId = getPortletIdFrom(compoundPortletId);
-      return id + FederatingPortletInvokerService.SEPARATOR + portletInvoker.createClone(portletId);
+      PortletContext portletContext = dereference(compoundPortletContext);
+      PortletContext cloneContext = portletInvoker.createClone(portletContext);
+      return reference(cloneContext);
    }
 
    public List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
@@ -165,37 +177,67 @@
       {
          return Collections.EMPTY_LIST;
       }
+
+      //
       List dereferencedList = new ArrayList(portletIds);
       for (int i = 0; i < dereferencedList.size(); i++)
       {
-         String compoundPortletId = (String)dereferencedList.get(i);
-         String portletId = getPortletIdFrom(compoundPortletId);
-         dereferencedList.set(i, portletId);
+         PortletContext compoundPortletContext = (PortletContext)dereferencedList.get(i);
+         PortletContext portletContext = dereference(compoundPortletContext);
+         dereferencedList.set(i, portletContext);
       }
-      return portletInvoker.destroyClones(portletIds);
+
+      //
+      List failures = portletInvoker.destroyClones(portletIds);
+      for (int i = 0; i < failures.size(); i++)
+      {
+         DestroyCloneFailure failure = (DestroyCloneFailure)failures.get(i);
+         String cloneId = failure.getPortletId();
+         failure = new DestroyCloneFailure(reference(cloneId));
+         failures.set(i, failure);
+      }
+
+      //
+      return failures;
    }
 
-   public PropertyMap getProperties(String compoundPortletId) throws PortletInvokerException
+   public PropertyMap getProperties(PortletContext compoundPortletContext) throws PortletInvokerException
    {
-      String portletId = getPortletIdFrom(compoundPortletId);
+      PortletContext portletId = dereference(compoundPortletContext);
       return portletInvoker.getProperties(portletId);
    }
 
-   public PropertyMap getProperties(String compoundPortletId, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   public PropertyMap getProperties(PortletContext compoundPortletContext, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      String portletId = getPortletIdFrom(compoundPortletId);
+      PortletContext portletId = dereference(compoundPortletContext);
       return portletInvoker.getProperties(portletId, keys);
    }
 
-   public void setProperties(String compoundPortletId, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   public PortletContext setProperties(PortletContext compoundPortletContext, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      String portletId = getPortletIdFrom(compoundPortletId);
-      portletInvoker.setProperties(portletId, changes);
+      PortletContext portletContext = dereference(compoundPortletContext);
+      portletContext = portletInvoker.setProperties(portletContext, changes);
+      return reference(portletContext);
    }
 
-   private String getPortletIdFrom(String compoundPortletId)
+   private String dereference(String compoundPortletId)
    {
       return compoundPortletId.substring(id.length() + 1);
    }
+
+   private PortletContext dereference(PortletContext compoundPortlet)
+   {
+      return new PortletContext(dereference(compoundPortlet.getId()), compoundPortlet.getMarshalldState());
+   }
+
+   private PortletContext reference(PortletContext portletContext)
+   {
+      return new PortletContext(reference(portletContext.getId()), portletContext.getMarshalldState());
+   }
+
+   private String reference(String portletId)
+   {
+      return id + FederatingPortletInvokerService.SEPARATOR + portletId;
+   }
 }
                         
\ No newline at end of file

Modified: trunk/federation/src/main/org/jboss/portal/federation/impl/FederatingPortletInvokerService.java
===================================================================
--- trunk/federation/src/main/org/jboss/portal/federation/impl/FederatingPortletInvokerService.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/federation/src/main/org/jboss/portal/federation/impl/FederatingPortletInvokerService.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -30,6 +30,7 @@
 import org.jboss.portal.portlet.NoSuchPortletException;
 import org.jboss.portal.portlet.Portlet;
 import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.PortletContext;
 import org.jboss.portal.portlet.invocation.PortletInvocation;
 import org.jboss.portal.jems.as.system.AbstractJBossService;
 
@@ -153,15 +154,15 @@
 
    public void invoke(PortletInvocation invocation) throws PortletInvokerException
    {
-      String compoundPortletId = (String)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE);
-      FederatedPortletInvoker federated = getFederatedPortletInvokerFor(compoundPortletId);
+      PortletContext compoundPortletContext = (PortletContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE);
+      FederatedPortletInvoker federated = getFederatedPortletInvokerFor(compoundPortletContext.getId());
       federated.invoke(invocation);
    }
 
-   public String createClone(String compoundPortletId) throws PortletInvokerException
+   public PortletContext createClone(PortletContext compoundPortletContext) throws PortletInvokerException
    {
-      FederatedPortletInvoker federated = getFederatedPortletInvokerFor(compoundPortletId);
-      return federated.createClone(compoundPortletId);
+      FederatedPortletInvoker federated = getFederatedPortletInvokerFor(compoundPortletContext.getId());
+      return federated.createClone(compoundPortletContext);
    }
 
    public List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
@@ -195,22 +196,22 @@
       return invoker.destroyClones(portletIds);
    }
 
-   public PropertyMap getProperties(String compoundPortletId, Set keys) throws PortletInvokerException
+   public PropertyMap getProperties(PortletContext compoundPortletContext, Set keys) throws PortletInvokerException
    {
-      FederatedPortletInvoker federated = getFederatedPortletInvokerFor(compoundPortletId);
-      return federated.getProperties(compoundPortletId, keys);
+      FederatedPortletInvoker federated = getFederatedPortletInvokerFor(compoundPortletContext.getId());
+      return federated.getProperties(compoundPortletContext, keys);
    }
 
-   public PropertyMap getProperties(String compoundPortletId) throws PortletInvokerException
+   public PropertyMap getProperties(PortletContext compoundPortletContext) throws PortletInvokerException
    {
-      FederatedPortletInvoker federated = getFederatedPortletInvokerFor(compoundPortletId);
-      return federated.getProperties(compoundPortletId);
+      FederatedPortletInvoker federated = getFederatedPortletInvokerFor(compoundPortletContext.getId());
+      return federated.getProperties(compoundPortletContext);
    }
 
-   public void setProperties(String compoundPortletId, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   public PortletContext setProperties(PortletContext compoundPortletContext, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      FederatedPortletInvoker federated = getFederatedPortletInvokerFor(compoundPortletId);
-      federated.setProperties(compoundPortletId, changes);
+      FederatedPortletInvoker federated = getFederatedPortletInvokerFor(compoundPortletContext.getId());
+      return federated.setProperties(compoundPortletContext, changes);
    }
 
    // Support methods **************************************************************************************************

Modified: trunk/portlet/build.xml
===================================================================
--- trunk/portlet/build.xml	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/build.xml	2006-09-12 16:51:45 UTC (rev 5180)
@@ -491,8 +491,11 @@
    <target name="test-framework" depends="init">
       <execute-tests>
          <x-test>
-            <test todir="${test.reports}" name="org.jboss.portal.test.portlet.deployment.UnmarshallerTestCase"/>
-            <test todir="${test.reports}" name="org.jboss.portal.test.portlet.state.StatefulPortletInvokerTestCase"/>
+            <!--<test todir="${test.reports}" name="org.jboss.portal.test.portlet.deployment.UnmarshallerTestCase"/>-->
+            <test todir="${test.reports}" name="org.jboss.portal.test.portlet.state.LocalStoreProducerStatefulPortletInvokerTestCase"/>
+            <test todir="${test.reports}" name="org.jboss.portal.test.portlet.state.RemoteStoreProducerStatefulPortletInvokerTestCase"/>
+            <test todir="${test.reports}" name="org.jboss.portal.test.portlet.state.LocalStoreConsumerStatefulPortletInvokerTestCase"/>
+            <test todir="${test.reports}" name="org.jboss.portal.test.portlet.state.RemoteStoreConsumerStatefulPortletInvokerTestCase"/>
             <test todir="${test.reports}" name="org.jboss.portal.test.portlet.PortletRequestDecoderTestCase"/>
             <test todir="${test.reports}" name="org.jboss.portal.test.portlet.ParametersTestCase"/>
             <test todir="${test.reports}" name="org.jboss.portal.test.portlet.PropertiesTestCase"/>

Added: trunk/portlet/src/main/org/jboss/portal/portlet/PortletClonedEvent.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/PortletClonedEvent.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/PortletClonedEvent.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,47 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class PortletClonedEvent extends StateEvent
+{
+
+   /** . */
+   private final String clonedId;
+
+   public PortletClonedEvent(String cloneId)
+   {
+      if (cloneId == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      this.clonedId = cloneId;
+   }
+
+   public String getClonedId()
+   {
+      return clonedId;
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/PortletContext.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/PortletContext.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/PortletContext.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,68 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet;
+
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class PortletContext implements Serializable
+{
+
+   /** . */
+   private final String id;
+
+   /** . */
+   private final byte[] marshalldState;
+
+   public PortletContext(String id)
+   {
+      this(id, null);
+   }
+
+   public PortletContext(String id, byte[] state)
+   {
+      if (id == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      this.id = id;
+      this.marshalldState = state;
+   }
+
+   public String getId()
+   {
+      return id;
+   }
+
+   public byte[] getMarshalldState()
+   {
+      return marshalldState;
+   }
+
+   public String toString()
+   {
+      return "PortletContext[" + id + "]";
+   }
+}

Deleted: trunk/portlet/src/main/org/jboss/portal/portlet/PortletInvoker.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/PortletInvoker.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/PortletInvoker.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,113 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.portlet;
-
-import org.jboss.portal.portlet.state.PropertyMap;
-import org.jboss.portal.portlet.state.PropertyChange;
-import org.jboss.portal.portlet.invocation.PortletInvocation;
-
-import java.util.Set;
-import java.util.List;
-
-/**
- * The <code>PortletInvoker</code> is an abstraction for a set of portlets. It defines a context for performing
- * operations are possible on a particular portlet among the set.
- *
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public interface PortletInvoker
-{
-   /**
-    * Return the set of portlet exposed.
-    *
-    * @return the set of exposed portlets
-    */
-   Set getPortlets() throws PortletInvokerException;
-
-   /**
-    * Get information about a specific portlet.
-    *
-    * @param portletId the portlet identifier in the context of this invoker
-    * @return the <code>PortletInfo</code> for the specified portlet
-    * @throws IllegalArgumentException if the portletId is null
-    */
-   Portlet getPortlet(String portletId) throws IllegalArgumentException, PortletInvokerException;
-
-   /**
-    * Invoke an operation on a specific portlet.
-    *
-    * @param invocation the portlet invocation
-    * @throws IllegalArgumentException if the invocation is null
-    */
-   void invoke(PortletInvocation invocation) throws IllegalArgumentException, PortletInvokerException;
-
-   /**
-    * Clone a portlet.
-    *
-    * @return the clone id
-    * @throws IllegalArgumentException if the portletId is null
-    * @throws UnsupportedOperationException if the invoker does not support this operation
-    */
-   String createClone(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
-
-   /**
-    * Destroy a cloned portlet.
-    *
-    * @param portletIds a list of portlet ids to destroy
-    * @return a list of portlet ids that were not destroyed during the operation
-    * @throws IllegalArgumentException if the portletId is null
-    * @throws UnsupportedOperationException if the invoker does not support this operation
-    */
-   List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
-
-   /**
-    * Return a subset of the properties of the specified portlet.
-    *
-    * @param portletId the portlet id
-    * @param keys the set of keys to retrieve
-    * @return the properties
-    * @throws IllegalArgumentException if the portletId or the keys arguments are null
-    * @throws UnsupportedOperationException if the invoker does not support this operation
-    */
-   PropertyMap getProperties(String portletId, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
-
-   /**
-    * Return all the properties of the specified portlet.
-    *
-    * @param portletId the portlet id
-    * @return the properties
-    * @throws IllegalArgumentException if the portletId is null
-    * @throws UnsupportedOperationException if the invoker does not support this operation
-    */
-   PropertyMap getProperties(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
-
-   /**
-    * Set the properties on the specified portlet.
-    *
-    * @param portletId  the portlet id
-    * @param changes the changes
-    * @throws IllegalArgumentException if the portletId or the properties is null
-    * @throws UnsupportedOperationException if the invoker does not support this operation
-    */
-   void setProperties(String portletId, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
-}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/PortletInvoker.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/PortletInvoker.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/PortletInvoker.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,113 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet;
+
+import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.Portlet;
+import org.jboss.portal.portlet.PortletContext;
+import org.jboss.portal.portlet.state.PropertyChange;
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public interface PortletInvoker
+{
+   /**
+    * Return the set of portlet exposed.
+    *
+    * @return the set of exposed portlets
+    */
+   Set getPortlets() throws PortletInvokerException;
+
+   /**
+    * Get information about a specific portlet.
+    *
+    * @param portletId the portlet identifier in the context of this invoker
+    * @return the <code>PortletInfo</code> for the specified portlet
+    * @throws IllegalArgumentException if the portletId is null
+    */
+   Portlet getPortlet(String portletId) throws IllegalArgumentException, PortletInvokerException;
+
+   /**
+    * Invoke an operation on a specific portlet.
+    *
+    * @param invocation the portlet invocation
+    * @throws IllegalArgumentException if the invocation is null
+    */
+   void invoke(PortletInvocation invocation) throws IllegalArgumentException, PortletInvokerException;
+
+   /**
+    * Clone a portlet.
+    *
+    * @return the clone id
+    * @throws IllegalArgumentException if the portletId is null
+    * @throws UnsupportedOperationException if the invoker does not support this operation
+    */
+   PortletContext createClone(PortletContext portletContext) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
+
+   /**
+    * Destroy a cloned portlet.
+    *
+    * @param portletContexts a list of portlet contexts to destroy
+    * @return a list of portlet ids that were not destroyed during the operation
+    * @throws IllegalArgumentException if the portletId is null
+    * @throws UnsupportedOperationException if the invoker does not support this operation
+    */
+   List destroyClones(List portletContexts) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
+
+   /**
+    * Return a subset of the properties of the specified portlet.
+    *
+    * @param portletContext the portlet context
+    * @param keys the set of keys to retrieve
+    * @return the properties
+    * @throws IllegalArgumentException if the portletId or the keys arguments are null
+    * @throws UnsupportedOperationException if the invoker does not support this operation
+    */
+   PropertyMap getProperties(PortletContext portletContext, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
+
+   /**
+    * Return all the properties of the specified portlet.
+    *
+    * @param portletContext the portlet context
+    * @return the properties
+    * @throws IllegalArgumentException if the portletId is null
+    * @throws UnsupportedOperationException if the invoker does not support this operation
+    */
+   PropertyMap getProperties(PortletContext portletContext) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
+
+   /**
+    * Set the properties on the specified portlet.
+    *
+    * @param portletContext the portlet context
+    * @param changes the changes
+    * @throws IllegalArgumentException if the portletId or the properties is null
+    * @throws UnsupportedOperationException if the invoker does not support this operation
+    */
+   PortletContext setProperties(PortletContext portletContext, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
+}

Deleted: trunk/portlet/src/main/org/jboss/portal/portlet/RenderURL.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/RenderURL.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/RenderURL.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,36 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.portlet;
-
-/**
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public interface RenderURL extends PortletURL
-{
-   /**
-    * Return the navigational state that may be null.
-    *
-    * @return the navigational state
-    */
-   StateString getNavigationalState();
-}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/RenderURL.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/RenderURL.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/RenderURL.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,36 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 2748 $
+ */
+public interface RenderURL extends PortletURL
+{
+   /**
+    * Return the navigational state that may be null.
+    *
+    * @return the navigational state
+    */
+   StateString getNavigationalState();
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/StateEvent.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/StateEvent.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/StateEvent.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet;
+
+/**
+ * An event that signals state modifications
+ *
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public abstract class StateEvent
+{
+}

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/container/PortletContainerInvoker.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/container/PortletContainerInvoker.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/container/PortletContainerInvoker.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -27,7 +27,7 @@
 import org.jboss.portal.common.invocation.InvocationHandler;
 import org.jboss.portal.portlet.state.PropertyMap;
 import org.jboss.portal.portlet.state.PropertyChange;
-import org.jboss.portal.portlet.PortletInvoker;
+import org.jboss.portal.portlet.stateful.PortletInvoker;
 import org.jboss.portal.portlet.Portlet;
 import org.jboss.portal.portlet.NoSuchPortletException;
 import org.jboss.portal.portlet.PortletInvokerException;
@@ -179,4 +179,4 @@
    {
       throw new UnsupportedOperationException();
    }
-}
+}
\ No newline at end of file

Added: trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/StateConverterService.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/StateConverterService.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/StateConverterService.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,61 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.impl.state;
+
+import org.jboss.portal.portlet.state.StateConverter;
+import org.jboss.portal.portlet.state.producer.ProducerState;
+import org.jboss.portal.jems.as.system.AbstractJBossService;
+import org.jboss.portal.common.util.Tools;
+
+import java.io.IOException;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class StateConverterService extends AbstractJBossService implements StateConverter
+{
+
+   public byte[] marshall(ProducerState state)
+   {
+      try
+      {
+         return Tools.serialize(state);
+      }
+      catch (IOException e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+
+   public ProducerState unmarshall(byte[] marshalledState)
+   {
+      try
+      {
+         return (ProducerState)Tools.unserialize(marshalledState);
+      }
+      catch (Exception e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/StateManagementPolicyService.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/StateManagementPolicyService.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/StateManagementPolicyService.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,51 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.impl.state;
+
+import org.jboss.portal.portlet.state.StateManagementPolicy;
+import org.jboss.portal.jems.as.system.AbstractJBossService;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class StateManagementPolicyService extends AbstractJBossService implements StateManagementPolicy
+{
+
+   /** . */
+   private boolean persistLocally;
+
+   public boolean getPersistLocally()
+   {
+      return persistLocally;
+   }
+
+   public void setPersistLocally(boolean persistLocally)
+   {
+      this.persistLocally = persistLocally;
+   }
+
+   public boolean persistLocally()
+   {
+      return persistLocally;
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/consumer/ConsumerPersistenceManagerService.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/consumer/ConsumerPersistenceManagerService.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/consumer/ConsumerPersistenceManagerService.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,110 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.impl.state.consumer;
+
+import org.jboss.portal.portlet.state.consumer.ConsumerPersistenceManager;
+import org.jboss.portal.portlet.state.consumer.ConsumerState;
+import org.jboss.portal.portlet.state.consumer.ConsumerStateContext;
+import org.jboss.portal.portlet.state.NoSuchStateException;
+import org.jboss.portal.portlet.state.InvalidStateIdException;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class ConsumerPersistenceManagerService implements ConsumerPersistenceManager
+{
+
+   /** . */
+   private Map store = new HashMap();
+
+   /** . */
+   private int counter = 0;
+
+   public synchronized ConsumerStateContext loadState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException
+   {
+      checkId(stateId);
+      ConsumerStateContext state = (ConsumerStateContext)store.get(stateId);
+      if (state == null)
+      {
+         throw new NoSuchStateException(stateId);
+      }
+      return state;
+   }
+
+   public synchronized String createState(ConsumerState state) throws IllegalArgumentException
+   {
+      if (state == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      ConsumerStateContext ctx = new ConsumerStateContext(Integer.toString(counter++), state.getPortletId(), state.getBytes());
+      store.put(ctx.getId(), ctx);
+      return ctx.getId();
+   }
+
+   public synchronized void updateState(String stateId, ConsumerState state) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException
+   {
+      checkId(stateId);
+      if (state == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (store.put(stateId, new ConsumerStateContext(stateId, state.getPortletId(), state.getBytes())) == null)
+      {
+         throw new NoSuchStateException(stateId);
+      }
+   }
+
+   public synchronized void destroyState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException
+   {
+      checkId(stateId);
+      if (store.remove(stateId) == null)
+      {
+         throw new NoSuchStateException(stateId);
+      }
+   }
+
+   public synchronized int getSize()
+   {
+      return store.size();
+   }
+
+   private void checkId(String stateId) throws IllegalArgumentException, InvalidStateIdException
+   {
+      if (stateId == null)
+      {
+         throw new IllegalArgumentException("No null state id accepted");
+      }
+      try
+      {
+         Integer.parseInt(stateId);
+      }
+      catch (NumberFormatException e)
+      {
+         throw new InvalidStateIdException(e, stateId);
+      }
+   }
+}

Copied: trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/producer/ProducerPersistenceManagerService.java (from rev 5145, trunk/portlet/src/main/org/jboss/portal/portlet/test/support/state/StateStoreSupport.java)
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/test/support/state/StateStoreSupport.java	2006-09-04 23:49:24 UTC (rev 5145)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/producer/ProducerPersistenceManagerService.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,137 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.impl.state.producer;
+
+import org.jboss.portal.portlet.state.SimplePropertyMap;
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.state.InvalidStateIdException;
+import org.jboss.portal.portlet.state.producer.ProducerPersistenceManager;
+import org.jboss.portal.portlet.state.producer.ProducerStateContext;
+import org.jboss.portal.portlet.state.NoSuchStateException;
+import org.jboss.portal.jems.as.system.AbstractJBossService;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision$
+ */
+public class ProducerPersistenceManagerService extends AbstractJBossService implements ProducerPersistenceManager
+{
+
+   /** . */
+   private Map store = new HashMap();
+
+   /** . */
+   private int counter = 0;
+
+   public synchronized ProducerStateContext loadState(String stateId) throws NoSuchStateException, InvalidStateIdException
+   {
+      if (stateId == null)
+      {
+         throw new IllegalArgumentException("No null state id accepted");
+      }
+      try
+      {
+         Integer.parseInt(stateId);
+      }
+      catch (NumberFormatException e)
+      {
+         throw new InvalidStateIdException(e, stateId);
+      }
+      ProducerStateContext state = (ProducerStateContext)store.get(stateId);
+      if (state == null)
+      {
+         throw new NoSuchStateException(stateId);
+      }
+      return state;
+   }
+
+   public synchronized String createState(String portletId, PropertyMap propertyMap)
+   {
+      if (portletId == null)
+      {
+         throw new IllegalArgumentException("No null portlet id accepted");
+      }
+      if (propertyMap == null)
+      {
+         throw new IllegalArgumentException("No null value map accepted");
+      }
+      String id = Integer.toString(counter++);
+      ProducerStateContext state = new ProducerStateContext(id, portletId, new SimplePropertyMap(propertyMap));
+      store.put(id, state);
+      return id;
+   }
+
+   public synchronized String cloneState(String stateId, PropertyMap propertyMap) throws NoSuchStateException, InvalidStateIdException
+   {
+      if (propertyMap == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      ProducerStateContext state = loadState(stateId);
+      return createState(state.getPortletId(), propertyMap);
+   }
+
+   public String cloneState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException
+   {
+      ProducerStateContext state = loadState(stateId);
+      return createState(state.getPortletId(), new SimplePropertyMap(state.getProperties()));
+   }
+
+   public synchronized void updateState(String stateId, PropertyMap propertyMap) throws NoSuchStateException, InvalidStateIdException
+   {
+      if (propertyMap == null)
+      {
+         throw new IllegalArgumentException("No null value map");
+      }
+      ProducerStateContext ctx = loadState(stateId);
+      ctx.getProperties().clear();
+      ctx.getProperties().putAll(propertyMap);
+   }
+
+   public synchronized void destroyState(String stateId) throws InvalidStateIdException, NoSuchStateException
+   {
+      if (stateId == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      try
+      {
+         Integer.parseInt(stateId);
+      }
+      catch (NumberFormatException e)
+      {
+         throw new InvalidStateIdException(e, stateId);
+      }
+      if (store.remove(stateId) == null)
+      {
+         throw new NoSuchStateException(stateId);
+      }
+   }
+
+   public synchronized int getSize()
+   {
+      return store.size(); 
+   }
+}


Property changes on: trunk/portlet/src/main/org/jboss/portal/portlet/impl/state/producer/ProducerPersistenceManagerService.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/invocation/PortletInvocation.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/invocation/PortletInvocation.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/invocation/PortletInvocation.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -57,8 +57,8 @@
    /** The attribute name under which the portlet id can be accessed. */
    public static final String PORTLET_ID_ATTRIBUTE = "portletid";
 
-   /** The attribute name under which the state store can be accessed. */
-   public static final String STATE_STORE_ATTRIBUTE = "statestore";
+   /** The attribute name under which the portlet id can be accessed. */
+   public static final String PORTLET_CONTEXT_ATTRIBUTE = "portletcontext";
 
    /** The attribute name under which the registry can be accessed. */
    public static final String PORTLET_INVOKER = "portletinvoker";

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/spi/InstanceContext.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/spi/InstanceContext.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/spi/InstanceContext.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -22,6 +22,7 @@
 package org.jboss.portal.portlet.spi;
 
 import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.StateEvent;
 
 /**
  * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
@@ -37,23 +38,16 @@
    String getId();
 
    /**
-    * The portlet is cloned and the state is managed by the producer
+    * Return the access mode to this portlet instance.
     *
-    * @param cloneId the portlet id of the clone
+    * @return the access mode
     */
-   void portletCloned(String cloneId);
+   AccessMode getAccessMode();
 
    /**
-    * The portlet is cloned and the state is managed by the consumer.
+    * A state event occured.
     *
-    * @param state the opaque state
+    * @param event the event
     */
-   void portletCloned(byte[] state);
-
-   /**
-    * Return the access mode to this portlet instance.
-    *
-    * @return the access mode
-    */
-   AccessMode getAccessMode();
+   void onStateEvent(StateEvent event);
 }

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/state/AbstractPropertyContext.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/AbstractPropertyContext.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/AbstractPropertyContext.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -23,7 +23,6 @@
 
 import org.jboss.portal.portlet.info.PreferencesInfo;
 import org.jboss.portal.portlet.info.PreferenceInfo;
-import org.jboss.portal.portlet.state.PropertyMap;
 import org.jboss.portal.common.value.Value;
 
 import java.util.Set;
@@ -43,7 +42,7 @@
    public static final int UPDATE_FAILED = 1;
 
    /** The state has been succesfully updated. */
-   public static final int UPDATE_SUCCEDED = 2;
+   public static final int UPDATE_SUCCESSFUL = 2;
 
    /** The user prefs. */
    private PropertyMap prefs;
@@ -108,7 +107,7 @@
             PropertyChange change = changes[i];
             prefs.setProperty(change.getKey(), change.getValue());
          }
-         status = UPDATE_SUCCEDED;
+         status = UPDATE_SUCCESSFUL;
       }
    }
 

Copied: trunk/portlet/src/main/org/jboss/portal/portlet/state/InvalidStateIdException.java (from rev 5145, trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/InvalidStateIdException.java)
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/InvalidStateIdException.java	2006-09-04 23:49:24 UTC (rev 5145)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/InvalidStateIdException.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,61 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision$
+ */
+public class InvalidStateIdException extends Exception
+{
+
+   private String stateId;
+
+   public InvalidStateIdException(String stateId)
+   {
+      super("No such state " + stateId);
+      this.stateId = stateId;
+   }
+
+   public InvalidStateIdException(String message, String portletId)
+   {
+      super(message);
+      this.stateId = portletId;
+   }
+
+   public InvalidStateIdException(Throwable cause, String portletId)
+   {
+      super(cause);
+      this.stateId = portletId;
+   }
+
+   public InvalidStateIdException(String message, Throwable cause, String portletId)
+   {
+      super(message, cause);
+      this.stateId = portletId;
+   }
+
+   public String getStateId()
+   {
+      return stateId;
+   }
+}


Property changes on: trunk/portlet/src/main/org/jboss/portal/portlet/state/InvalidStateIdException.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Copied: trunk/portlet/src/main/org/jboss/portal/portlet/state/NoSuchStateException.java (from rev 5145, trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/NoSuchStateException.java)
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/NoSuchStateException.java	2006-09-04 23:49:24 UTC (rev 5145)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/NoSuchStateException.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,61 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision$
+ */
+public class NoSuchStateException extends Exception
+{
+
+   private String stateId;
+
+   public NoSuchStateException(String stateId)
+   {
+      super("No such state " + stateId);
+      this.stateId = stateId;
+   }
+
+   public NoSuchStateException(String message, String portletId)
+   {
+      super(message);
+      this.stateId = portletId;
+   }
+
+   public NoSuchStateException(Throwable cause, String portletId)
+   {
+      super(cause);
+      this.stateId = portletId;
+   }
+
+   public NoSuchStateException(String message, Throwable cause, String portletId)
+   {
+      super(message, cause);
+      this.stateId = portletId;
+   }
+
+   public String getStateId()
+   {
+      return stateId;
+   }
+}


Property changes on: trunk/portlet/src/main/org/jboss/portal/portlet/state/NoSuchStateException.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/PortletClonedEvent.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/PortletClonedEvent.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/PortletClonedEvent.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,50 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state;
+
+import org.jboss.portal.portlet.StateEvent;
+import org.jboss.portal.portlet.PortletContext;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class PortletClonedEvent extends StateEvent
+{
+
+   /** . */
+   private final PortletContext clonedContext;
+
+   public PortletClonedEvent(PortletContext clonedContext)
+   {
+      if (clonedContext == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      this.clonedContext = clonedContext;
+   }
+
+   public PortletContext getClonedContext()
+   {
+      return clonedContext;
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/PortletModifiedEvent.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/PortletModifiedEvent.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/PortletModifiedEvent.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,50 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state;
+
+import org.jboss.portal.portlet.StateEvent;
+import org.jboss.portal.portlet.PortletContext;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class PortletModifiedEvent extends StateEvent
+{
+
+   /** . */
+   private final PortletContext modifiedContext;
+
+   public PortletModifiedEvent(PortletContext clonedContext)
+   {
+      if (clonedContext == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      this.modifiedContext = clonedContext;
+   }
+
+   public PortletContext getModifiedContext()
+   {
+      return modifiedContext;
+   }
+}

Deleted: trunk/portlet/src/main/org/jboss/portal/portlet/state/PropertyMap.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/PropertyMap.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/PropertyMap.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,55 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.portlet.state;
-
-import org.jboss.portal.common.value.Value;
-
-import java.util.Set;
-import java.util.Map;
-
-/**
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public interface PropertyMap extends Map
-{
-   /**
-    * Return the value for the given key or null if it does not exist.
-    *
-    * @param key the requested key
-    * @return the requested value or null if it does not exist
-    * @throws IllegalArgumentException if the key is null
-    */
-   Value getProperty(String key) throws IllegalArgumentException;
-
-   /**
-    * Update the value of the given key. If the value object is null
-    * it means that the entry must be removed. Implementation can throw
-    * an unsupported operation exception when it is abnormal to perform an update.
-    *
-    * @param key the key to update
-    * @param value the new value
-    * @throws UnsupportedOperationException if the operation is not supported
-    * @throws IllegalArgumentException if the key is null
-    */
-   void setProperty(String key, Value value) throws IllegalArgumentException, UnsupportedOperationException;
-}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/PropertyMap.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/PropertyMap.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/PropertyMap.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,56 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state;
+
+import org.jboss.portal.common.value.Value;
+
+import java.util.Set;
+import java.util.Map;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 3287 $
+ */
+public interface PropertyMap extends Map, Serializable
+{
+   /**
+    * Return the value for the given key or null if it does not exist.
+    *
+    * @param key the requested key
+    * @return the requested value or null if it does not exist
+    * @throws IllegalArgumentException if the key is null
+    */
+   Value getProperty(String key) throws IllegalArgumentException;
+
+   /**
+    * Update the value of the given key. If the value object is null
+    * it means that the entry must be removed. Implementation can throw
+    * an unsupported operation exception when it is abnormal to perform an update.
+    *
+    * @param key the key to update
+    * @param value the new value
+    * @throws UnsupportedOperationException if the operation is not supported
+    * @throws IllegalArgumentException if the key is null
+    */
+   void setProperty(String key, Value value) throws IllegalArgumentException, UnsupportedOperationException;
+}

Deleted: trunk/portlet/src/main/org/jboss/portal/portlet/state/SimplePropertyMap.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/SimplePropertyMap.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/SimplePropertyMap.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,68 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.portlet.state;
-
-import java.util.Map;
-import java.util.HashMap;
-
-/**
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public class SimplePropertyMap extends AbstractPropertyMap
-{
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -5889928820592375820L;
-
-   protected Map getDelegate()
-   {
-      return values;
-   }
-
-   /** . */
-   protected final Map values;
-
-   public SimplePropertyMap()
-   {
-      this(new HashMap());
-   }
-
-   public SimplePropertyMap(PropertyMap that)
-   {
-      this();
-      if (that == null)
-      {
-         throw new IllegalArgumentException();
-      }
-      putAll(that);
-   }
-
-   public SimplePropertyMap(Map map)
-   {
-      if (map == null)
-      {
-         throw new IllegalArgumentException();
-      }
-      this.values = map;
-   }
-}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/SimplePropertyMap.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/SimplePropertyMap.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/SimplePropertyMap.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,71 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state;
+
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.state.AbstractPropertyMap;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 3287 $
+ */
+public class SimplePropertyMap extends AbstractPropertyMap
+{
+
+   /** The serialVersionUID */
+   private static final long serialVersionUID = -5889928820592375820L;
+
+   protected Map getDelegate()
+   {
+      return values;
+   }
+
+   /** . */
+   protected final Map values;
+
+   public SimplePropertyMap()
+   {
+      this(new HashMap());
+   }
+
+   public SimplePropertyMap(PropertyMap that)
+   {
+      this();
+      if (that == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      putAll(that);
+   }
+
+   public SimplePropertyMap(Map map)
+   {
+      if (map == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      this.values = map;
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/StateConverter.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/StateConverter.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/StateConverter.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,35 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state;
+
+import org.jboss.portal.portlet.state.producer.ProducerState;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public interface StateConverter
+{
+   byte[] marshall(ProducerState state);
+
+   ProducerState unmarshall(byte[] marshalledState);
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/StateManagementPolicy.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/StateManagementPolicy.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/StateManagementPolicy.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,36 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public interface StateManagementPolicy
+{
+   /**
+    * Returns true if the state must be persisted locally.
+    *
+    * @return true if state must be persisted locally
+    */
+   boolean persistLocally();
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerPersistenceManager.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerPersistenceManager.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerPersistenceManager.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,72 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state.consumer;
+
+import org.jboss.portal.portlet.state.InvalidStateIdException;
+import org.jboss.portal.portlet.state.NoSuchStateException;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public interface ConsumerPersistenceManager
+{
+   /**
+    * Load the state.
+    *
+    * @param stateId the state id
+    * @return the value map or null if it does not exist
+    * @throws IllegalArgumentException if the state id is null
+    * @throws NoSuchStateException is the specified state does not exist
+    * @throws InvalidStateIdException if the state id is not valid
+    */
+   ConsumerStateContext loadState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
+
+   /**
+    * Create the initial state.
+    *
+    * @return the id of the state created
+    * @throws IllegalArgumentException if the portlet id is null
+    */
+   String createState(ConsumerState state) throws IllegalArgumentException;
+
+   /**
+    * Update the state.
+    *
+    * @param stateId
+    * @param propertyMap the updated state
+    * @throws IllegalArgumentException if the state id is null or the values are null
+    * @throws NoSuchStateException is the specified state does not exist
+    * @throws InvalidStateIdException if the state id is not valid
+    */
+   void updateState(String stateId, ConsumerState propertyMap) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
+
+   /**
+    * Destroy the state.
+    *
+    * @param stateId
+    * @throws IllegalArgumentException if the state id is null
+    * @throws NoSuchStateException is the specified state does not exist
+    * @throws InvalidStateIdException if the state id is not valid
+    */
+   void destroyState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerPortletInvoker.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerPortletInvoker.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerPortletInvoker.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,412 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state.consumer;
+
+import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.Portlet;
+import org.jboss.portal.portlet.NoSuchPortletException;
+import org.jboss.portal.portlet.InvalidPortletIdException;
+import org.jboss.portal.portlet.StateEvent;
+import org.jboss.portal.portlet.PortletContext;
+import org.jboss.portal.portlet.spi.InstanceContext;
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.state.PropertyChange;
+import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.state.NoSuchStateException;
+import org.jboss.portal.portlet.state.InvalidStateIdException;
+import org.jboss.portal.portlet.PortletInvoker;
+import org.jboss.portal.portlet.state.PortletClonedEvent;
+import org.jboss.portal.portlet.state.PortletModifiedEvent;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+import org.jboss.portal.common.invocation.AttributeResolver;
+import org.jboss.portal.common.NotYetImplemented;
+
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class ConsumerPortletInvoker implements org.jboss.portal.portlet.stateful.PortletInvoker
+{
+
+   /** . */
+   private static final String CLONE_ID_PREFIX = "@";
+
+   /** . */
+   private PortletInvoker producer;
+
+   /** . */
+   private ConsumerPersistenceManager persistenceManager;
+
+   public PortletContext unwrapCCP(String wrappedCCP) throws InvalidPortletIdException
+   {
+      if (wrappedCCP == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (wrappedCCP.startsWith(CLONE_ID_PREFIX) == false)
+      {
+         throw new InvalidPortletIdException(wrappedCCP);
+      }
+      return new PortletContext(wrappedCCP.substring(1));
+   }
+
+   public PortletContext unwrapPOP(String wrappedPOPId) throws InvalidPortletIdException
+   {
+      if (wrappedPOPId == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      return new PortletContext(wrappedPOPId);
+   }
+
+   public String wrapCCP(PortletContext ccpCtx) throws InvalidPortletIdException
+   {
+      if (ccpCtx == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      return CLONE_ID_PREFIX + ccpCtx.getId();
+   }
+
+   public String wrapPOP(PortletContext popCtx) throws InvalidPortletIdException
+   {
+      if (popCtx == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (popCtx.getId().startsWith(CLONE_ID_PREFIX))
+      {
+         throw new IllegalArgumentException("Must not start with " + CLONE_ID_PREFIX);
+      }
+      return popCtx.getId();
+   }
+
+   public PortletInvoker getProducer()
+   {
+      return producer;
+   }
+
+   public void setProducer(PortletInvoker producer)
+   {
+      this.producer = producer;
+   }
+
+   public void setPersistenceManager(ConsumerPersistenceManager persistenceManager)
+   {
+      this.persistenceManager = persistenceManager;
+   }
+
+   public Set getPortlets() throws PortletInvokerException
+   {
+      return producer.getPortlets();
+   }
+
+   public Portlet getPortlet(String portletId) throws IllegalArgumentException, PortletInvokerException
+   {
+      PortletContext portletCtx = getPortletContext(portletId);
+      return producer.getPortlet(portletCtx.getId());
+   }
+
+   public void invoke(PortletInvocation invocation) throws IllegalArgumentException, PortletInvokerException
+   {
+      AttributeResolver resolver  = invocation.getContext().getAttributeResolver(PortletInvocation.REQUEST_SCOPE);
+      if (resolver == null)
+      {
+         throw new IllegalArgumentException();
+      }
+
+      String portletId = (String)resolver.getAttribute(PortletInvocation.PORTLET_ID_ATTRIBUTE);
+      if (portletId == null)
+      {
+         throw new IllegalArgumentException();
+      }
+
+      //
+      ConsumerPortletContext portletContext = getPortletContext(portletId);
+
+      //
+      InstanceContext cictx = invocation.getInstanceContext();
+      StatefulInstanceContextImpl pictx = new StatefulInstanceContextImpl(cictx);
+
+      try
+      {
+         resolver.setAttribute(PortletInvocation.PORTLET_ID_ATTRIBUTE, null);
+         resolver.setAttribute(PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, portletContext);
+         invocation.setInstanceContext(pictx);
+
+         //
+         producer.invoke(invocation);
+
+         //
+         if (pictx.clonedContext != null)
+         {
+            if (pictx.clonedContext.getMarshalldState() != null)
+            {
+               // Save the clone state
+               ConsumerState state = new ConsumerState(pictx.clonedContext.getId(), pictx.clonedContext.getMarshalldState());
+               String stateId = persistenceManager.createState(state);
+               String clonedId = CLONE_ID_PREFIX + stateId;
+               org.jboss.portal.portlet.PortletClonedEvent event = new org.jboss.portal.portlet.PortletClonedEvent(clonedId);
+               cictx.onStateEvent(event);
+            }
+            else
+            {
+               org.jboss.portal.portlet.PortletClonedEvent event = new org.jboss.portal.portlet.PortletClonedEvent(pictx.clonedContext.getId());
+               cictx.onStateEvent(event);
+            }
+         }
+         else if (pictx.modifiedContext != null)
+         {
+            // Save
+            if (pictx.modifiedContext.getMarshalldState() != null)
+            {
+               try
+               {
+                  ConsumerState state = new ConsumerState(pictx.modifiedContext.getId(), pictx.modifiedContext.getMarshalldState());
+                  persistenceManager.updateState(portletContext.stateId, state);
+               }
+               catch (NoSuchStateException e)
+               {
+                  e.printStackTrace();
+               }
+               catch (InvalidStateIdException e)
+               {
+                  e.printStackTrace();
+               }
+            }
+         }
+      }
+      finally
+      {
+         resolver.setAttribute(PortletInvocation.PORTLET_ID_ATTRIBUTE, portletId);
+         resolver.setAttribute(PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, null);
+         invocation.setInstanceContext(cictx);
+      }
+   }
+
+   public String createClone(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      PortletContext portletCtx = getPortletContext(portletId);
+
+      //
+      PortletContext cloneContext = producer.createClone(portletCtx);
+
+      //
+      if (cloneContext.getMarshalldState() != null)
+      {
+         ConsumerState state = new ConsumerState(cloneContext.getId(), cloneContext.getMarshalldState());
+         String id = persistenceManager.createState(state);
+         return CLONE_ID_PREFIX + id;
+      }
+      else
+      {
+         return cloneContext.getId();
+      }
+   }
+
+   public List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      if (portletIds == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      List portletContexts = new ArrayList(portletIds);
+      for (int i = 0; i < portletContexts.size(); i++)
+      {
+         String portletId = (String)portletContexts.get(i);
+         ConsumerPortletContext portletContext = getPortletContext(portletId);
+         portletContexts.set(i, portletContext);
+         if (portletContext.stateId != null)
+         {
+            try
+            {
+               persistenceManager.destroyState(portletContext.stateId);
+            }
+            catch (NoSuchStateException e)
+            {
+               //
+            }
+            catch (InvalidStateIdException e)
+            {
+               //
+            }
+         }
+      }
+
+      //
+      List failures = producer.destroyClones(portletContexts);
+
+//      for (Iterator i = failures.iterator(); i.hasNext();)
+//      {
+//         DestroyCloneFailure failure = (DestroyCloneFailure)i.next();
+//         //
+//      }
+
+      //
+      return failures;
+   }
+
+   public PropertyMap getProperties(String portletId, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      PortletContext portletContext = getPortletContext(portletId);
+      return producer.getProperties(portletContext, keys);
+   }
+
+   public PropertyMap getProperties(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      PortletContext portletContext = getPortletContext(portletId);
+      return producer.getProperties(portletContext);
+   }
+
+   public void setProperties(String portletId, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      ConsumerPortletContext portletContext = getPortletContext(portletId);
+
+      //
+      PortletContext updatedPortletContext = producer.setProperties(portletContext, changes);
+
+      //
+      if (updatedPortletContext.getMarshalldState() != null)
+      {
+         if (portletContext.stateId == null)
+         {
+            throw new NotYetImplemented();
+         }
+
+         //
+         ConsumerState state = new ConsumerState(updatedPortletContext.getId(), updatedPortletContext.getMarshalldState());
+         try
+         {
+            persistenceManager.updateState(portletContext.stateId, state);
+         }
+         catch (NoSuchStateException e)
+         {
+            // What to do ?
+         }
+         catch (InvalidStateIdException e)
+         {
+            // What to do ?
+         }
+      }
+      else
+      {
+         if (portletContext.stateId != null)
+         {
+            throw new NotYetImplemented();
+         }
+      }
+   }
+
+   private static class StatefulInstanceContextImpl implements InstanceContext
+   {
+
+      /** . */
+      private InstanceContext cictx;
+
+      /** . */
+      private PortletContext clonedContext;
+
+      /** . */
+      private PortletContext modifiedContext;
+
+      public StatefulInstanceContextImpl(InstanceContext cictx)
+      {
+         this.cictx = cictx;
+      }
+
+      public String getId()
+      {
+         return cictx.getId();
+      }
+
+      public AccessMode getAccessMode()
+      {
+         return cictx.getAccessMode();
+      }
+
+      public void onStateEvent(StateEvent event)
+      {
+         if (event instanceof PortletClonedEvent)
+         {
+            PortletClonedEvent pce = (PortletClonedEvent)event;
+            clonedContext = pce.getClonedContext();
+         }
+         else if (event instanceof PortletModifiedEvent)
+         {
+            PortletModifiedEvent pce = (PortletModifiedEvent)event;
+            modifiedContext = pce.getModifiedContext();
+         }
+      }
+   }
+
+   private ConsumerPortletContext getPortletContext(String portletId) throws IllegalArgumentException, NoSuchPortletException, InvalidPortletIdException
+   {
+      if (portletId == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (portletId.startsWith(CLONE_ID_PREFIX))
+      {
+         String stateId = portletId.substring(1);
+         try
+         {
+            ConsumerStateContext stateCtx = persistenceManager.loadState(stateId);
+            return new ConsumerPortletContext(stateId, stateCtx.getPortletId(), stateCtx.getBytes());
+         }
+         catch (NoSuchStateException e)
+         {
+            throw new NoSuchPortletException(portletId);
+         }
+         catch (InvalidStateIdException e)
+         {
+            throw new InvalidPortletIdException(portletId);
+         }
+      }
+      else
+      {
+         return new ConsumerPortletContext(null, portletId);
+      }
+   }
+
+   private class ConsumerPortletContext extends PortletContext
+   {
+
+      /** . */
+      private final String stateId;
+
+      public ConsumerPortletContext(String stateId, String id)
+      {
+         super(id);
+         this.stateId = stateId;
+      }
+
+      public ConsumerPortletContext(String stateId, String id, byte[] state)
+      {
+         super(id, state);
+         this.stateId = stateId;
+      }
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerState.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerState.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerState.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,81 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state.consumer;
+
+import java.util.Date;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class ConsumerState
+{
+
+   /** . */
+   private String portletId;
+
+   /** . */
+   private byte[] bytes;
+
+   /** . */
+   private Date terminationTime;
+
+   public ConsumerState(String porteltId, byte[] bytes)
+   {
+      if (porteltId == null)
+      {
+         throw new IllegalArgumentException("No portlet id provided");
+      }
+      if (bytes == null)
+      {
+         throw new IllegalArgumentException("No bytes provided");
+      }
+      this.portletId = porteltId;
+      this.bytes = bytes;
+   }
+
+   /**
+    *
+    */
+   public String getPortletId()
+   {
+      return portletId;
+   }
+
+   /**
+    *
+    */
+   public byte[] getBytes()
+   {
+      return bytes;
+   }
+
+   /**
+    * The scheduled termination time.
+    *
+    * @return the termination time
+    */
+   public Date getTerminationTime()
+   {
+      return terminationTime;
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerStateContext.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerStateContext.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/consumer/ConsumerStateContext.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,52 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state.consumer;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class ConsumerStateContext extends ConsumerState
+{
+
+   /** . */
+   private final String id;
+
+   public ConsumerStateContext(String id, String portletId, byte[] bytes)
+   {
+      super(portletId, bytes);
+
+      //
+      if (id == null)
+      {
+         throw new IllegalArgumentException();
+      }
+
+      //
+      this.id = id;
+   }
+
+   public String getId()
+   {
+      return id;
+   }
+}

Deleted: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/InvalidStateIdException.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/InvalidStateIdException.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/InvalidStateIdException.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,61 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.portlet.state.producer;
-
-/**
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public class InvalidStateIdException extends Exception
-{
-
-   private String stateId;
-
-   public InvalidStateIdException(String stateId)
-   {
-      super("No such state " + stateId);
-      this.stateId = stateId;
-   }
-
-   public InvalidStateIdException(String message, String portletId)
-   {
-      super(message);
-      this.stateId = portletId;
-   }
-
-   public InvalidStateIdException(Throwable cause, String portletId)
-   {
-      super(cause);
-      this.stateId = portletId;
-   }
-
-   public InvalidStateIdException(String message, Throwable cause, String portletId)
-   {
-      super(message, cause);
-      this.stateId = portletId;
-   }
-
-   public String getStateId()
-   {
-      return stateId;
-   }
-}

Deleted: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/NoSuchStateException.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/NoSuchStateException.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/NoSuchStateException.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,61 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.portlet.state.producer;
-
-/**
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public class NoSuchStateException extends Exception
-{
-
-   private String stateId;
-
-   public NoSuchStateException(String stateId)
-   {
-      super("No such state " + stateId);
-      this.stateId = stateId;
-   }
-
-   public NoSuchStateException(String message, String portletId)
-   {
-      super(message);
-      this.stateId = portletId;
-   }
-
-   public NoSuchStateException(Throwable cause, String portletId)
-   {
-      super(cause);
-      this.stateId = portletId;
-   }
-
-   public NoSuchStateException(String message, Throwable cause, String portletId)
-   {
-      super(message, cause);
-      this.stateId = portletId;
-   }
-
-   public String getStateId()
-   {
-      return stateId;
-   }
-}

Copied: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerPersistenceManager.java (from rev 5145, trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StateStore.java)
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StateStore.java	2006-09-04 23:49:24 UTC (rev 5145)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerPersistenceManager.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,99 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state.producer;
+
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.state.InvalidStateIdException;
+import org.jboss.portal.portlet.state.NoSuchStateException;
+
+/**
+ * An abstraction for enabling state management on the producer side.
+ *
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision$
+ */
+public interface ProducerPersistenceManager
+{
+   /**
+    * Load the state.
+    *
+    * @param stateId the state id
+    * @return the value map or null if it does not exist
+    * @throws IllegalArgumentException if the state id is null
+    * @throws NoSuchStateException is the specified state does not exist
+    * @throws InvalidStateIdException if the state id is not valid
+    */
+   ProducerStateContext loadState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
+
+   /**
+    * Create the initial state.
+    *
+    * @param portletId the id that this state refers to
+    * @return the id of the state created
+    * @throws IllegalArgumentException if the portlet id is null
+    */
+   String createState(String portletId, PropertyMap propertyMap) throws IllegalArgumentException;
+
+   /**
+    * Clone an existing state.
+    *
+    * @param stateId the id that this state refers to
+    * @return the state id
+    * @throws IllegalArgumentException if the state id is null
+    * @throws NoSuchStateException is the specified state does not exist
+    * @throws InvalidStateIdException if the state id is not valid
+    */
+   String cloneState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
+
+   /**
+    * Clone an existing state.
+    *
+    * @param stateId the id that this state refers to
+    * @param propertyMap the values of the cloned state
+    * @return the state id
+    * @throws IllegalArgumentException if the state id is null or the value is nul
+    * @throws NoSuchStateException is the specified state does not exist
+    * @throws InvalidStateIdException if the state id is not valid
+    */
+   String cloneState(String stateId, PropertyMap propertyMap) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
+
+   /**
+    * Update the state.
+    *
+    * @param stateId
+    * @param propertyMap the updated state
+    * @throws IllegalArgumentException if the state id is null or the values are null
+    * @throws NoSuchStateException is the specified state does not exist
+    * @throws org.jboss.portal.portlet.state.InvalidStateIdException if the state id is not valid
+    */
+   void updateState(String stateId, PropertyMap propertyMap) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
+
+   /**
+    * Destroy the state.
+    *
+    * @param stateId
+    * @throws IllegalArgumentException if the state id is null
+    * @throws NoSuchStateException is the specified state does not exist
+    * @throws InvalidStateIdException if the state id is not valid
+    */
+   void destroyState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
+}


Property changes on: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerPersistenceManager.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Copied: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerPortletInvoker.java (from rev 5145, trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StatefulPortletInvoker.java)
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StatefulPortletInvoker.java	2006-09-04 23:49:24 UTC (rev 5145)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerPortletInvoker.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,724 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state.producer;
+
+import org.jboss.portal.common.invocation.InvocationException;
+import org.jboss.portal.portlet.state.SimplePropertyMap;
+import org.jboss.portal.common.value.Value;
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.NoSuchPortletException;
+import org.jboss.portal.portlet.Portlet;
+import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.InvalidPortletIdException;
+import org.jboss.portal.portlet.PortletContext;
+import org.jboss.portal.portlet.PortletInvoker;
+import org.jboss.portal.portlet.spi.InstanceContext;
+import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.state.AbstractPropertyContext;
+import org.jboss.portal.portlet.state.PropertyChange;
+import org.jboss.portal.portlet.state.DestroyCloneFailure;
+import org.jboss.portal.portlet.state.StateManagementPolicy;
+import org.jboss.portal.portlet.state.StateConverter;
+import org.jboss.portal.portlet.state.InvalidStateIdException;
+import org.jboss.portal.portlet.state.NoSuchStateException;
+import org.jboss.portal.portlet.state.PortletClonedEvent;
+import org.jboss.portal.portlet.state.PortletModifiedEvent;
+import org.jboss.portal.portlet.info.PreferenceInfo;
+import org.jboss.portal.portlet.info.PreferencesInfo;
+import org.jboss.portal.portlet.info.PortletInfo;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+import org.jboss.portal.portlet.invocation.ActionInvocation;
+import org.jboss.portal.jems.as.system.AbstractJBossService;
+
+import java.util.Iterator;
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision$
+ */
+public class ProducerPortletInvoker extends AbstractJBossService implements PortletInvoker
+{
+
+   /** . */
+   private static final String CLONE_ID_PREFIX = "_";
+
+   /** . */
+   private org.jboss.portal.portlet.stateful.PortletInvoker portletInvoker;
+
+   /** . */
+   private ProducerPersistenceManager persistenceManager;
+
+   /** . */
+   private StateManagementPolicy stateManagementPolicy;
+
+   /** . */
+   private StateConverter stateConverter;
+
+   public org.jboss.portal.portlet.stateful.PortletInvoker getPortletInvoker()
+   {
+      return portletInvoker;
+   }
+
+   public void setPortletInvoker(org.jboss.portal.portlet.stateful.PortletInvoker portletInvoker)
+   {
+      this.portletInvoker = portletInvoker;
+   }
+
+   public ProducerPersistenceManager getPersistenceManager()
+   {
+      return persistenceManager;
+   }
+
+   public void setPersistenceManager(ProducerPersistenceManager ppm)
+   {
+      this.persistenceManager = ppm;
+   }
+
+   public StateManagementPolicy getStateManagementPolicy()
+   {
+      return stateManagementPolicy;
+   }
+
+   public void setStateManagementPolicy(StateManagementPolicy stateManagementPolicy)
+   {
+      this.stateManagementPolicy = stateManagementPolicy;
+   }
+
+   public StateConverter getStateConverter()
+   {
+      return stateConverter;
+   }
+
+   public void setStateConverter(StateConverter stateConverter)
+   {
+      this.stateConverter = stateConverter;
+   }
+
+   public String unwrapCCP(PortletContext wrappedCCPCtx) throws InvalidPortletIdException
+   {
+      if (wrappedCCPCtx == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (wrappedCCPCtx.getId().startsWith(CLONE_ID_PREFIX) == false)
+      {
+         throw new InvalidPortletIdException(wrappedCCPCtx.getId());
+      }
+      return wrappedCCPCtx.getId().substring(1);
+   }
+
+   public String unwrapPOP(PortletContext wrappedPOPCtx) throws InvalidPortletIdException
+   {
+      if (wrappedPOPCtx == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      return wrappedPOPCtx.getId();
+   }
+
+   public PortletContext wrapCCP(String ccpId) throws InvalidPortletIdException
+   {
+      if (ccpId == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      return new PortletContext(CLONE_ID_PREFIX + ccpId);
+   }
+
+   public PortletContext wrapPOP(String popId) throws InvalidPortletIdException
+   {
+      if (popId == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (popId.startsWith(CLONE_ID_PREFIX))
+      {
+         throw new IllegalArgumentException("Must not start with " + CLONE_ID_PREFIX);
+      }
+      return new PortletContext(popId);
+   }
+
+   public Set getPortlets() throws PortletInvokerException
+   {
+      return portletInvoker.getPortlets();
+   }
+
+   public Portlet getPortlet(String portletId) throws PortletInvokerException
+   {
+      if (portletId == null)
+      {
+         throw new IllegalArgumentException("No null portlet id accepted");
+      }
+      if (portletId.startsWith(CLONE_ID_PREFIX))
+      {
+         try
+         {
+            ProducerState state = persistenceManager.loadState(portletId.substring(1));
+            return portletInvoker.getPortlet(state.getPortletId());
+         }
+         catch (NoSuchStateException e)
+         {
+            throw new NoSuchPortletException(e, portletId);
+         }
+         catch (InvalidStateIdException e)
+         {
+            throw new InvalidPortletIdException(e, portletId);
+         }
+      }
+      else
+      {
+         return portletInvoker.getPortlet(portletId);
+      }
+   }
+
+   public void invoke(PortletInvocation invocation) throws PortletInvokerException, InvocationException
+   {
+      // Get the context of the portlet that the client want to use
+      PortletContext portletContext = (PortletContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE);
+      if (portletContext == null)
+      {
+         throw new InvocationException("No portlet context provided");
+      }
+
+      // Get the access mode
+      InstanceContext instanceCtx = invocation.getInstanceContext();
+      AccessMode access = instanceCtx.getAccessMode();
+
+      // Value map of the state loaded
+      PropertyMap propertyMap = null;
+
+      // The next portlet to invoke
+      String portletId = portletContext.getId();
+
+      // Try to get state
+      ProducerState state = getState(portletContext);
+      if (state != null)
+      {
+         propertyMap = state.getProperties();
+         portletId = state.getPortletId();
+      }
+      else
+      {
+         // If it is a producer offered portlet we consider read-write as read-only
+         if (access == AccessMode.READ_WRITE)
+         {
+            access = AccessMode.READ_ONLY;
+         }
+      }
+
+      // Get the portlet container and set it on invocation
+      Portlet portlet = portletInvoker.getPortlet(portletId);
+      if (portlet == null)
+      {
+         throw new NoSuchPortletException("Portlet " + portletId + " not found", portletId);
+      }
+      PortletInfo info = portlet.getInfo();
+
+      // Create prefs and set it on invocation
+      PreferencesInfo prefsInfo = info.getPreferences();
+
+      //
+      AbstractPropertyContext prefs = new AbstractPropertyContext(access, propertyMap, prefsInfo);
+
+      //
+      try
+      {
+         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, portletId);
+         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE, prefs);
+         invocation.setInfo(info);
+
+         // Invoke
+         portletInvoker.invoke(invocation);
+      }
+      finally
+      {
+         invocation.removeAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE);
+         invocation.removeAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
+         invocation.setInfo(null);
+      }
+
+      //
+      int status = prefs.getStatus();
+
+      // Producer state management if the invocation was succesful
+      if (invocation instanceof ActionInvocation && status == AbstractPropertyContext.UPDATE_SUCCESSFUL)
+      {
+         // Get the potentially updated prefs
+         PropertyMap newPrefs = prefs.getPrefs();
+
+         //
+         if (access == AccessMode.CLONE_BEFORE_WRITE)
+         {
+            // Create the state
+            if (state != null)
+            {
+               boolean persist = stateManagementPolicy.persistLocally();
+               if (persist)
+               {
+                  try
+                  {
+                     // The state id should be ok as it was used before to load the state
+                     String portletStateId = ((ProducerStateContext)state).getId();
+                     String cloneStateId = persistenceManager.cloneState(portletStateId, newPrefs);
+
+                     // Return the clone context
+                     String cloneId = CLONE_ID_PREFIX + cloneStateId;
+                     PortletContext clonedCtx = new PortletContext(cloneId);
+                     PortletClonedEvent event = new PortletClonedEvent(clonedCtx);
+                     instanceCtx.onStateEvent(event);
+                  }
+                  catch (NoSuchStateException e)
+                  {
+                     throw new PortletInvokerException("Unexpected exception", e);
+                  }
+                  catch (InvalidStateIdException e)
+                  {
+                     throw new PortletInvokerException("Unexpected exception", e);
+                  }
+               }
+               else
+               {
+                  ProducerState cloneState = new ProducerState(state.getPortletId(), newPrefs);
+                  byte[] bytes = stateConverter.marshall(cloneState);
+                  String cloneId = CLONE_ID_PREFIX + "dumbvalue";
+                  PortletContext clonedCtx = new PortletContext(cloneId, bytes);
+                  PortletClonedEvent event = new PortletClonedEvent(clonedCtx);
+                  instanceCtx.onStateEvent(event);
+               }
+            }
+            else
+            {
+               // Add the missing mutable portlet state
+               for (Iterator i = prefsInfo.getKeys().iterator(); i.hasNext();)
+               {
+                  String key = (String)i.next();
+                  if (!newPrefs.keySet().contains(key))
+                  {
+                     PreferenceInfo pref = prefsInfo.getPreference(key);
+                     if (Boolean.TRUE.equals(pref.isReadOnly()) == false)
+                     {
+                        newPrefs.setProperty(key, pref.getDefaultValue());
+                     }
+                  }
+               }
+
+               // Create the new state
+               String cloneStateId = persistenceManager.createState(portletId, newPrefs);
+
+               // Return the clone context
+               String cloneId = CLONE_ID_PREFIX + cloneStateId;
+               PortletContext clonedCtx = new PortletContext(cloneId);
+               PortletClonedEvent event = new PortletClonedEvent(clonedCtx);
+               instanceCtx.onStateEvent(event);
+            }
+         }
+         else if (access == AccessMode.READ_WRITE)
+         {
+            if (portletContext.getMarshalldState() == null)
+            {
+               // Update the state
+               try
+               {
+                  String portletStateId = ((ProducerStateContext)state).getId();
+                  persistenceManager.updateState(portletStateId, newPrefs);
+               }
+               catch (NoSuchStateException e)
+               {
+                  throw new PortletInvokerException("Unexpected exception", e);
+               }
+               catch (InvalidStateIdException e)
+               {
+                  throw new PortletInvokerException("Unexpected exception", e);
+               }
+            }
+            else
+            {
+               ProducerState cloneState = new ProducerState(portletId, newPrefs);
+               byte[] bytes = stateConverter.marshall(cloneState);
+               PortletContext modifiedCtx = new PortletContext(portletId, bytes);
+               PortletModifiedEvent event = new PortletModifiedEvent(modifiedCtx);
+               instanceCtx.onStateEvent(event);
+            }
+         }
+         else if (access == AccessMode.READ_ONLY)
+         {
+            throw new InvocationException("Read only portlet should have not been modified");
+         }
+      }
+   }
+
+   public PortletContext createClone(PortletContext portletContext) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      if (portletContext == null)
+      {
+         throw new IllegalArgumentException("No null portlet context accepted");
+      }
+
+      //
+      String portletId = portletContext.getId();
+      ProducerState state = getState(portletContext);
+      boolean useStore = stateManagementPolicy.persistLocally();
+
+      //
+      if (state != null)
+      {
+         if (useStore)
+         {
+            try
+            {
+               String stateId = portletId.substring(1);
+               String cloneId = CLONE_ID_PREFIX + persistenceManager.cloneState(stateId);
+               return new PortletContext(cloneId);
+            }
+            catch (NoSuchStateException e)
+            {
+               throw new NoSuchPortletException(e, portletId);
+            }
+            catch (InvalidStateIdException e)
+            {
+               throw new InvalidPortletIdException(e, portletId);
+            }
+         }
+         else
+         {
+            String cloneId = CLONE_ID_PREFIX + "dumbvalue";
+            byte[] marshalledState = stateConverter.marshall(state);
+            return new PortletContext(cloneId, marshalledState);
+         }
+      }
+      else
+      {
+         PropertyMap originalState = getPropertiesFromMetaData(portletId);
+         PropertyMap newState = new SimplePropertyMap();
+         for (Iterator i = originalState.keySet().iterator(); i.hasNext();)
+         {
+            String key = (String)i.next();
+            Value originalValue = originalState.getProperty(key);
+            newState.setProperty(key, originalValue);
+         }
+         if (useStore)
+         {
+            String cloneId = persistenceManager.createState(portletId, newState);
+            return new PortletContext(CLONE_ID_PREFIX + cloneId);
+         }
+         else
+         {
+            String cloneId = CLONE_ID_PREFIX + "dumbvalue";
+            ProducerState sstate = new ProducerState(portletId, newState);
+            byte[] marshalledState = stateConverter.marshall(sstate);
+            return new PortletContext(cloneId, marshalledState);
+         }
+      }
+   }
+
+   public List destroyClones(List portletContexts) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      if (portletContexts == null)
+      {
+         throw new IllegalArgumentException("No portlet contexts provided");
+      }
+
+      //
+      List result = new ArrayList();
+      for (Iterator i = portletContexts.iterator(); i.hasNext();)
+      {
+         PortletContext portletContext = (PortletContext)i.next();
+
+         // We only take care of producer hosted state
+         if (portletContext.getMarshalldState() == null)
+         {
+            String portletId = portletContext.getId();
+            if (portletId.startsWith(CLONE_ID_PREFIX) == false)
+            {
+               log.debug("Attempt to destroy a producer offered portlet " + portletId);
+               DestroyCloneFailure failure = new DestroyCloneFailure(portletId, "Cannot destroy POP");
+               result.add(failure);
+            }
+            else
+            {
+               try
+               {
+                  persistenceManager.destroyState(portletId.substring(1));
+               }
+               catch (NoSuchStateException e)
+               {
+                  log.debug("Attempt to destroy a non existing portlet " + portletId);
+                  DestroyCloneFailure failure = new DestroyCloneFailure(portletId, "Not found");
+                  result.add(failure);
+               }
+               catch (InvalidStateIdException e)
+               {
+                  log.debug("Attempt to destroy a non valid portlet " + portletId);
+                  DestroyCloneFailure failure = new DestroyCloneFailure(portletId, "Invalid portlet id");
+                  result.add(failure);
+               }
+            }
+         }
+      }
+      return result;
+   }
+
+   public PropertyMap getProperties(PortletContext portletContext, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      if (keys == null)
+      {
+         throw new IllegalArgumentException("No keys provided");
+      }
+      PropertyMap props = getProperties(portletContext);
+      props.keySet().retainAll(keys);
+      return props;
+   }
+
+   public PropertyMap getProperties(PortletContext portletContext) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      if (portletContext == null)
+      {
+         throw new IllegalArgumentException("No null portlet id is accepted");
+      }
+
+      //
+      String portletId = portletContext.getId();
+      ProducerState state = getState(portletContext);
+
+      //
+      if (state != null)
+      {
+         //
+         // Get the content
+         PropertyMap props = new SimplePropertyMap(state.getProperties());
+
+         // Dereference the portlet
+         String referencedPortletId = state.getPortletId();
+
+         // Get the container
+         Portlet referencedPortlet = portletInvoker.getPortlet(referencedPortletId);
+
+         // We need the referenced portlet
+         if (referencedPortlet == null)
+         {
+            throw new PortletInvokerException("The portlet " + referencedPortletId  + " referenced by this clone " + portletId + " is not available");
+         }
+
+         // Get the portlet info
+         PortletInfo referencedPortletInfo = referencedPortlet.getInfo();
+
+         // Add missing or read only properties from the referenced portlet
+         PreferencesInfo prefs = referencedPortletInfo.getPreferences();
+         for (Iterator i = prefs.getKeys().iterator(); i.hasNext();)
+         {
+            String key = (String)i.next();
+            PreferenceInfo pref = prefs.getPreference(key);
+            if (Boolean.TRUE.equals(pref.isReadOnly()) || props.keySet().contains(pref.getKey()) == false)
+            {
+               Value defaultValue = pref.getDefaultValue();
+               props.setProperty(key, (Value)defaultValue.clone());
+            }
+         }
+
+         //
+         return props;
+      }
+      else
+      {
+         // Get the container
+         return getPropertiesFromMetaData(portletId);
+      }
+   }
+
+   public PortletContext setProperties(PortletContext portletContext, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   {
+      if (portletContext == null)
+      {
+         throw new IllegalArgumentException("No null portlet id accepted");
+      }
+      if (changes == null)
+      {
+         throw new IllegalArgumentException("No null changes accepted");
+      }
+      for (int i = 0; i < changes.length; i++)
+      {
+         PropertyChange change = changes[i];
+         if (change == null)
+         {
+            throw new IllegalArgumentException("No null change accepted");
+         }
+      }
+
+      //
+      String portletId = portletContext.getId();
+      ProducerState state = getState(portletContext);
+
+      //
+      if (state == null)
+      {
+         throw new InvalidPortletIdException("Cannot configure producer offered portlets", portletId);
+      }
+
+      // Dereference the portlet
+      String referencedPortletId = state.getPortletId();
+
+      // Get the container
+      Portlet referencedPortlet = portletInvoker.getPortlet(referencedPortletId);
+
+      // We need the referenced portlet
+      if (referencedPortlet == null)
+      {
+         throw new PortletInvokerException("The portlet " + referencedPortletId  + " referenced by this clone " + portletId + " is not available");
+      }
+
+      // Get the portlet info
+      PortletInfo referencedPortletInfo = referencedPortlet.getInfo();
+
+      //
+      PreferencesInfo prefs = referencedPortletInfo.getPreferences();
+
+      // Clone the current state
+      PropertyMap properties = new SimplePropertyMap(state.getProperties());
+
+      // Clone argument
+      for (int i = 0; i < changes.length; i++)
+      {
+         PropertyChange change = changes[i];
+         String key = change.getKey();
+         int type = change.getType();
+
+         // If the original value exist and is read only we perform a reset instead
+         PreferenceInfo pref = prefs.getPreference(key);
+         if (pref != null)
+         {
+            if (Boolean.TRUE.equals(pref.isReadOnly()))
+            {
+               type = PropertyChange.PREF_RESET;
+            }
+         }
+
+         //
+         if (type == PropertyChange.PREF_UPDATE)
+         {
+            properties.setProperty(key, change.getValue());
+         }
+         else
+         {
+            properties.remove(key);
+         }
+      }
+
+      //
+      if (portletContext.getMarshalldState() == null)
+      {
+         String stateId = ((ProducerStateContext)state).getId();
+         try
+         {
+            persistenceManager.updateState(stateId, properties);
+         }
+         catch (NoSuchStateException e)
+         {
+            throw new NoSuchPortletException(e, portletId);
+         }
+         catch (InvalidStateIdException e)
+         {
+            throw new InvalidPortletIdException(e, portletId);
+         }
+         return new PortletContext(portletId);
+      }
+      else
+      {
+         ProducerState sstate = new ProducerState(referencedPortletId, properties);
+         byte[] marshalledState = stateConverter.marshall(sstate);
+         return new PortletContext(portletId, marshalledState);
+      }
+   }
+
+   /**
+    * Retrieve the properties from the portlet meta data.
+    *
+    * @param portletId the portlet id
+    * @return the properties
+    * @throws PortletInvokerException
+    */
+   private PropertyMap getPropertiesFromMetaData(String portletId) throws PortletInvokerException
+   {
+      //
+      Portlet portlet = portletInvoker.getPortlet(portletId);
+
+      // The prefs info
+      PreferencesInfo prefs = portlet.getInfo().getPreferences();
+
+      // Get the state
+      PropertyMap property = new SimplePropertyMap();
+      for (Iterator i = prefs.getKeys().iterator(); i.hasNext();)
+      {
+         String key = (String)i.next();
+         PreferenceInfo pref = prefs.getPreference(key);
+         property.setProperty(key, (Value)pref.getDefaultValue().clone());
+      }
+
+      //
+      return property;
+   }
+
+   /**
+    * Return the producer state from the specified portlet context or null if that portlet context
+    * reference a producer offered portlet.
+    *
+    * @param portletContext the portlet context
+    * @return the state that the portlet context carries
+    * @throws NoSuchPortletException if the underlying state does not exist
+    * @throws InvalidPortletIdException if the state id is not valid
+    */
+   private ProducerState getState(PortletContext portletContext) throws NoSuchPortletException, InvalidPortletIdException
+   {
+      if (portletContext.getMarshalldState() == null)
+      {
+         String portletId = portletContext.getId();
+         if (portletContext.getId().startsWith(CLONE_ID_PREFIX) == true)
+         {
+            String stateId =  portletId.substring(1);
+            try
+            {
+               return persistenceManager.loadState(stateId);
+            }
+            catch (NoSuchStateException e)
+            {
+               throw new NoSuchPortletException(e, portletId);
+            }
+            catch (InvalidStateIdException e)
+            {
+               throw new InvalidPortletIdException(e, portletId);
+            }
+         }
+         else
+         {
+            return null;
+         }
+      }
+      else
+      {
+         byte[] marshalledState = portletContext.getMarshalldState();
+         ProducerState state = stateConverter.unmarshall(marshalledState);
+         return state;
+      }
+   }
+}


Property changes on: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerPortletInvoker.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Copied: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerState.java (from rev 5145, trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/State.java)
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/State.java	2006-09-04 23:49:24 UTC (rev 5145)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerState.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,85 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state.producer;
+
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.state.SimplePropertyMap;
+
+import java.util.Date;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision$
+ */
+public class ProducerState implements Serializable
+{
+
+   /** . */
+   private String portletId;
+
+   /** . */
+   private PropertyMap properties;
+
+   /** . */
+   private Date terminationTime;
+
+   public ProducerState(String portletId)
+   {
+      this(portletId, new SimplePropertyMap());
+   }
+
+   public ProducerState(String portletId, PropertyMap properties)
+   {
+      if (portletId == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (properties == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      this.portletId = portletId;
+      this.properties = properties;
+      this.terminationTime = null;
+   }
+
+   public String getPortletId()
+   {
+      return portletId;
+   }
+
+   public PropertyMap getProperties()
+   {
+      return properties;
+   }
+
+   public Date getTerminationTime()
+   {
+      return terminationTime;
+   }
+
+   public void setTerminationTime(Date terminationTime)
+   {
+      this.terminationTime = terminationTime;
+   }
+}


Property changes on: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerState.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Added: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerStateContext.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerStateContext.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/ProducerStateContext.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,66 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.state.producer;
+
+import org.jboss.portal.portlet.state.PropertyMap;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class ProducerStateContext extends ProducerState
+{
+
+   /** . */
+   private final String id;
+
+   public ProducerStateContext(String id, String portletId)
+   {
+      super(portletId);
+
+      //
+      if (id == null)
+      {
+         throw new IllegalArgumentException();
+      }
+
+      //
+      this.id = id;
+   }
+
+   public ProducerStateContext(String id, String portletId, PropertyMap properties)
+   {
+      super(portletId, properties);
+
+      //
+      if (id == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      this.id = id;
+   }
+
+   public String getId()
+   {
+      return id;
+   }
+}

Deleted: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/State.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/State.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/State.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,66 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.portlet.state.producer;
-
-import org.jboss.portal.portlet.state.PropertyMap;
-
-import java.util.Date;
-
-/**
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public interface State
-{
-   /**
-    * Return the state id.
-    *
-    * @return the state id
-    */
-   String getId();
-
-   /**
-    * Return the portlet id this state refers to.
-    *
-    * @return the portlet id
-    */
-   String getPortletId();
-
-   /**
-    * The state properties.
-    *
-    * @return the state properties
-    */
-   PropertyMap getProperties();
-
-   /**
-    * The scheduled termination time.
-    *
-    * @return the termination time
-    */
-   Date getTerminationTime();
-
-   /**
-    * Set the termination time value.
-    */
-   void setTerminationTime(Date terminationTime);
-}

Deleted: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StateStore.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StateStore.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StateStore.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,97 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.portlet.state.producer;
-
-import org.jboss.portal.portlet.state.PropertyMap;
-
-/**
- * An abstraction for enabling state management on the producer side.
- *
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public interface StateStore
-{
-   /**
-    * Load the state.
-    *
-    * @param stateId the state id
-    * @return the value map or null if it does not exist
-    * @throws IllegalArgumentException if the state id is null
-    * @throws NoSuchStateException is the specified state does not exist
-    * @throws InvalidStateIdException if the state id is not valid
-    */
-   State loadState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
-
-   /**
-    * Create the initial state.
-    *
-    * @param portletId the id that this state refers to
-    * @return the id of the state created
-    * @throws IllegalArgumentException if the portlet id is null
-    */
-   String createState(String portletId, PropertyMap propertyMap) throws IllegalArgumentException;
-
-   /**
-    * Clone an existing state.
-    *
-    * @param stateId the id that this state refers to
-    * @return the state id
-    * @throws IllegalArgumentException if the state id is null
-    * @throws NoSuchStateException is the specified state does not exist
-    * @throws InvalidStateIdException if the state id is not valid
-    */
-   String cloneState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
-
-   /**
-    * Clone an existing state.
-    *
-    * @param stateId the id that this state refers to
-    * @param propertyMap the values of the cloned state
-    * @return the state id
-    * @throws IllegalArgumentException if the state id is null or the value is nul
-    * @throws NoSuchStateException is the specified state does not exist
-    * @throws InvalidStateIdException if the state id is not valid
-    */
-   String cloneState(String stateId, PropertyMap propertyMap) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
-
-   /**
-    * Update the state.
-    *
-    * @param stateId
-    * @param propertyMap the updated state
-    * @throws IllegalArgumentException if the state id is null or the values are null
-    * @throws NoSuchStateException is the specified state does not exist
-    * @throws InvalidStateIdException if the state id is not valid
-    */
-   void updateState(String stateId, PropertyMap propertyMap) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
-
-   /**
-    * Destroy the state.
-    *
-    * @param stateId
-    * @throws IllegalArgumentException if the state id is null
-    * @throws NoSuchStateException is the specified state does not exist
-    * @throws InvalidStateIdException if the state id is not valid
-    */
-   void destroyState(String stateId) throws IllegalArgumentException, NoSuchStateException, InvalidStateIdException;
-}

Deleted: trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StatefulPortletInvoker.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StatefulPortletInvoker.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/state/producer/StatefulPortletInvoker.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,628 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.portlet.state.producer;
-
-import org.jboss.portal.common.invocation.InvocationException;
-import org.jboss.portal.portlet.state.SimplePropertyMap;
-import org.jboss.portal.common.value.Value;
-import org.jboss.portal.portlet.state.PropertyMap;
-import org.jboss.portal.portlet.NoSuchPortletException;
-import org.jboss.portal.portlet.Portlet;
-import org.jboss.portal.portlet.PortletInvoker;
-import org.jboss.portal.portlet.PortletInvokerException;
-import org.jboss.portal.portlet.InvalidPortletIdException;
-import org.jboss.portal.portlet.state.AccessMode;
-import org.jboss.portal.portlet.state.AbstractPropertyContext;
-import org.jboss.portal.portlet.state.PropertyChange;
-import org.jboss.portal.portlet.state.DestroyCloneFailure;
-import org.jboss.portal.portlet.info.PreferenceInfo;
-import org.jboss.portal.portlet.info.PreferencesInfo;
-import org.jboss.portal.portlet.info.PortletInfo;
-import org.jboss.portal.portlet.invocation.PortletInvocation;
-import org.jboss.portal.portlet.invocation.ActionInvocation;
-import org.jboss.portal.jems.as.system.AbstractJBossService;
-
-import java.util.Iterator;
-import java.util.Set;
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public class StatefulPortletInvoker extends AbstractJBossService implements PortletInvoker
-{
-
-   /** . */
-   private static final String CLONE_ID_PREFIX = "_";
-
-   /** . */
-   private PortletInvoker portletInvoker;
-
-   /** . */
-   private StateStore stateStore;
-
-   public PortletInvoker getPortletInvoker()
-   {
-      return portletInvoker;
-   }
-
-   public void setPortletInvoker(PortletInvoker portletInvoker)
-   {
-      this.portletInvoker = portletInvoker;
-   }
-
-   public StateStore getStateStore()
-   {
-      return stateStore;
-   }
-
-   public void setStateStore(StateStore stateStore)
-   {
-      this.stateStore = stateStore;
-   }
-
-   public String unwrapCCPId(String wrappedCCPId) throws InvalidPortletIdException
-   {
-      if (wrappedCCPId == null)
-      {
-         throw new IllegalArgumentException();
-      }
-      if (wrappedCCPId.startsWith("_") == false)
-      {
-         throw new InvalidPortletIdException(wrappedCCPId);
-      }
-      return wrappedCCPId.substring(1);
-   }
-
-   public String unwrapPOPId(String wrappedPOPId) throws InvalidPortletIdException
-   {
-      if (wrappedPOPId == null)
-      {
-         throw new IllegalArgumentException();
-      }
-      return wrappedPOPId;
-   }
-
-   public String wrapCCPId(String ccpId) throws InvalidPortletIdException
-   {
-      if (ccpId == null)
-      {
-         throw new IllegalArgumentException();
-      }
-      return "_" + ccpId;
-   }
-
-   public String wrapPOPId(String popId) throws InvalidPortletIdException
-   {
-      if (popId == null)
-      {
-         throw new IllegalArgumentException();
-      }
-      if (popId.startsWith("_"))
-      {
-         throw new IllegalArgumentException("Must not start with _");
-      }
-      return popId;
-   }
-
-   public Set getPortlets() throws PortletInvokerException
-   {
-      return portletInvoker.getPortlets();
-   }
-
-   public Portlet getPortlet(String portletId) throws PortletInvokerException
-   {
-      if (portletId == null)
-      {
-         throw new IllegalArgumentException("No null portlet id accepted");
-      }
-      if (portletId.startsWith(CLONE_ID_PREFIX))
-      {
-         try
-         {
-            State state = stateStore.loadState(portletId.substring(1));
-            return portletInvoker.getPortlet(state.getPortletId());
-         }
-         catch (NoSuchStateException e)
-         {
-            throw new NoSuchPortletException(e, portletId);
-         }
-         catch (InvalidStateIdException e)
-         {
-            throw new InvalidPortletIdException(e, portletId);
-         }
-      }
-      else
-      {
-         return portletInvoker.getPortlet(portletId);
-      }
-   }
-
-   public void invoke(PortletInvocation invocation) throws PortletInvokerException, InvocationException
-   {
-      // Get the id of the portlet that the client want
-      String wantedPortletId = (String)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE);
-      if (wantedPortletId == null)
-      {
-         throw new InvocationException("No portlet id provided");
-      }
-
-      //
-      if (stateStore == null)
-      {
-         throw new InvocationException("No state store provided");
-      }
-
-      //
-      if (portletInvoker == null)
-      {
-         throw new InvocationException("No portlet invoker provided");
-      }
-
-
-      // Get the portle access mode
-      AccessMode access = invocation.getInstanceContext().getAccessMode();
-      if (invocation instanceof ActionInvocation && access == null)
-      {
-         throw new InvocationException("No access mode provided");
-      }
-
-      // Value map of the state loaded
-      PropertyMap propertyMap = null;
-
-      // State id not null implies that we have an existing state
-      String stateId = null;
-
-      // The next portlet to invoke
-      String portletId = wantedPortletId;
-
-      //
-      if (wantedPortletId.startsWith("_"))
-      {
-         //
-         stateId = wantedPortletId.substring(1);
-         State state;
-         try
-         {
-            state = stateStore.loadState(stateId);
-         }
-         catch (NoSuchStateException e)
-         {
-            throw new NoSuchPortletException(e, wantedPortletId);
-         }
-         catch (InvalidStateIdException e)
-         {
-            throw new InvalidPortletIdException(e, wantedPortletId);
-         }
-
-         //
-         propertyMap = state.getProperties();
-         portletId = state.getPortletId();
-      }
-
-      // If it is a producer offered portlet we consider read-write as read-only
-      if (access == AccessMode.READ_WRITE && stateId == null)
-      {
-         access = AccessMode.READ_ONLY;
-      }
-
-      // Get the portlet container and set it on invocation
-      Portlet portlet = portletInvoker.getPortlet(portletId);
-      if (portlet == null)
-      {
-         throw new NoSuchPortletException("Portlet " + portletId + " not found", portletId);
-      }
-      PortletInfo info = portlet.getInfo();
-
-      // Create prefs and set it on invocation
-      PreferencesInfo prefsInfo = info.getPreferences();
-
-      //
-      AbstractPropertyContext prefs = new AbstractPropertyContext(access, propertyMap, prefsInfo);
-
-      //
-      try
-      {
-         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, portletId);
-         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE, prefs);
-         invocation.setInfo(info);
-
-         // Invoke
-         portletInvoker.invoke(invocation);
-      }
-      finally
-      {
-         invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, wantedPortletId);
-         invocation.removeAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
-         invocation.setInfo(null);
-      }
-
-      //
-      int status = prefs.getStatus();
-
-      // Producer state management if the invocation was succesful
-      if (invocation instanceof ActionInvocation && status == AbstractPropertyContext.UPDATE_SUCCEDED)
-      {
-         // Get the potentially updated prefs
-         PropertyMap newPrefs = prefs.getPrefs();
-
-         //
-         if (access == AccessMode.CLONE_BEFORE_WRITE)
-         {
-            // Create the state
-            if (stateId != null)
-            {
-               try
-               {
-                  // The state id should be ok as it was used before to load the state
-                  stateId = stateStore.cloneState(stateId, newPrefs);
-               }
-               catch (NoSuchStateException e)
-               {
-                  throw new PortletInvokerException("Unexpected exception", e);
-               }
-               catch (InvalidStateIdException e)
-               {
-                  throw new PortletInvokerException("Unexpected exception", e);
-               }
-            }
-            else
-            {
-               // Add the missing mutable portlet state
-               for (Iterator i = prefsInfo.getKeys().iterator(); i.hasNext();)
-               {
-                  String key = (String)i.next();
-                  if (!newPrefs.keySet().contains(key))
-                  {
-                     PreferenceInfo pref = prefsInfo.getPreference(key);
-                     if (Boolean.TRUE.equals(pref.isReadOnly()) == false)
-                     {
-                        newPrefs.setProperty(key, pref.getDefaultValue());
-                     }
-                  }
-               }
-
-               // Create the new state
-               stateId = stateStore.createState(portletId, newPrefs);
-            }
-
-            // Return the new state id
-            String cloneId = CLONE_ID_PREFIX + stateId;
-
-            // Make a callback for the clone id creation
-            invocation.getInstanceContext().portletCloned(cloneId);
-         }
-         else if (access == AccessMode.READ_WRITE)
-         {
-            // Update the state
-            try
-            {
-               // the state id should be ok as it was used before to load the state
-               stateStore.updateState(stateId, newPrefs);
-            }
-            catch (NoSuchStateException e)
-            {
-               throw new PortletInvokerException("Unexpected exception", e);
-            }
-            catch (InvalidStateIdException e)
-            {
-               throw new PortletInvokerException("Unexpected exception", e);
-            }
-         }
-         else if (access == AccessMode.READ_ONLY)
-         {
-            throw new InvocationException("Read only portlet should have not been modified");
-         }
-      }
-   }
-
-   public String createClone(String portletId) throws PortletInvokerException
-   {
-      if (portletId == null)
-      {
-         throw new IllegalArgumentException("No null portlet id accepted");
-      }
-      if (portletId.startsWith(CLONE_ID_PREFIX))
-      {
-         try
-         {
-            String stateId = portletId.substring(1);
-            String cloneId = CLONE_ID_PREFIX + stateStore.cloneState(stateId);
-            return cloneId;
-         }
-         catch (NoSuchStateException e)
-         {
-            throw new NoSuchPortletException(e, portletId);
-         }
-         catch (InvalidStateIdException e)
-         {
-            throw new InvalidPortletIdException(e, portletId);
-         }
-      }
-      else
-      {
-         PropertyMap originalState = getPropertiesFromMetaData(portletId);
-         PropertyMap newState = new SimplePropertyMap();
-         for (Iterator i = originalState.keySet().iterator(); i.hasNext();)
-         {
-            String key = (String)i.next();
-            Value originalValue = originalState.getProperty(key);
-            newState.setProperty(key, originalValue);
-         }
-         String cloneId = CLONE_ID_PREFIX + stateStore.createState(portletId, newState);
-         return cloneId;
-      }
-   }
-
-   public List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
-   {
-      if (portletIds == null)
-      {
-         throw new IllegalArgumentException("No portlet ids provided");
-      }
-      List result = new ArrayList();
-      for (int i = 0; i < portletIds.size(); i++)
-      {
-         final String portletId = (String)portletIds.get(i);
-         if (portletId.startsWith(CLONE_ID_PREFIX) == false)
-         {
-            log.debug("Attempt to destroy a producer offered portlet " + portletId);
-            DestroyCloneFailure failure = new DestroyCloneFailure(portletId, "Cannot destroy POP");
-            result.add(failure);
-         }
-         else
-         {
-            try
-            {
-               stateStore.destroyState(portletId.substring(1));
-            }
-            catch (NoSuchStateException e)
-            {
-               log.debug("Attempt to destroy a non existing portlet " + portletId);
-               DestroyCloneFailure failure = new DestroyCloneFailure(portletId, "Not found");
-               result.add(failure);
-            }
-            catch (InvalidStateIdException e)
-            {
-               log.debug("Attempt to destroy a non valid portlet " + portletId);
-               DestroyCloneFailure failure = new DestroyCloneFailure(portletId, "Invalid portlet id");
-               result.add(failure);
-            }
-         }
-      }
-      return result;
-   }
-
-   public PropertyMap getProperties(String portletId, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
-   {
-      if (keys == null)
-      {
-         throw new IllegalArgumentException("Keys must not be null");
-      }
-      PropertyMap props = getProperties(portletId);
-      props.keySet().retainAll(keys);
-      return props;
-   }
-
-   public PropertyMap getProperties(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
-   {
-      if (portletId == null)
-      {
-         throw new IllegalArgumentException("No null portlet id is accepted");
-      }
-      if (portletId.startsWith(CLONE_ID_PREFIX))
-      {
-         // Get state id
-         String stateId = portletId.substring(1);
-
-         //
-         try
-         {
-            // Load state from store
-            State state = stateStore.loadState(stateId);
-
-            // Get the content
-            PropertyMap props = new SimplePropertyMap(state.getProperties());
-
-            // Dereference the portlet
-            String referencedPortletId = state.getPortletId();
-
-            // Get the container
-            Portlet referencedPortlet = portletInvoker.getPortlet(referencedPortletId);
-
-            // We need the referenced portlet
-            if (referencedPortlet == null)
-            {
-               throw new PortletInvokerException("The portlet " + referencedPortletId  + " referenced by this clone " + portletId + " is not available");
-            }
-
-            // Get the portlet info
-            PortletInfo referencedPortletInfo = referencedPortlet.getInfo();
-
-            // Add missing or read only properties from the referenced portlet
-            PreferencesInfo prefs = referencedPortletInfo.getPreferences();
-            for (Iterator i = prefs.getKeys().iterator(); i.hasNext();)
-            {
-               String key = (String)i.next();
-               PreferenceInfo pref = prefs.getPreference(key);
-               if (Boolean.TRUE.equals(pref.isReadOnly()) || props.keySet().contains(pref.getKey()) == false)
-               {
-                  Value defaultValue = pref.getDefaultValue();
-                  props.setProperty(key, (Value)defaultValue.clone());
-               }
-            }
-
-            //
-            return props;
-         }
-         catch (NoSuchStateException e)
-         {
-            throw new NoSuchPortletException(e, portletId);
-         }
-         catch (InvalidStateIdException e)
-         {
-            throw new InvalidPortletIdException(e, portletId);
-         }
-      }
-      else
-      {
-         // Get the container
-         return getPropertiesFromMetaData(portletId);
-      }
-   }
-
-   public void setProperties(String portletId, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
-   {
-      if (portletId == null)
-      {
-         throw new IllegalArgumentException("No null portlet id accepted");
-      }
-      if (changes == null)
-      {
-         throw new IllegalArgumentException("No null changes accepted");
-      }
-      for (int i = 0; i < changes.length; i++)
-      {
-         PropertyChange change = changes[i];
-         if (change == null)
-         {
-            throw new IllegalArgumentException("No null change accepted");
-         }
-      }
-      if (portletId.startsWith(CLONE_ID_PREFIX) == false)
-      {
-         throw new InvalidPortletIdException("Cannot configure producer offered portlets", portletId);
-      }
-      try
-      {
-         String stateId =  portletId.substring(1);
-
-         // Load the state
-         State state = stateStore.loadState(stateId);
-
-         // Dereference the portlet
-         String referencedPortletId = state.getPortletId();
-
-         // Get the container
-         Portlet referencedPortlet = portletInvoker.getPortlet(referencedPortletId);
-
-         // We need the referenced portlet
-         if (referencedPortlet == null)
-         {
-            throw new PortletInvokerException("The portlet " + referencedPortletId  + " referenced by this clone " + portletId + " is not available");
-         }
-
-         // Get the portlet info
-         PortletInfo referencedPortletInfo = referencedPortlet.getInfo();
-
-         //
-         PreferencesInfo prefs = referencedPortletInfo.getPreferences();
-
-         // Clone the current state
-         PropertyMap properties = new SimplePropertyMap(state.getProperties());
-
-         // Clone argument
-         for (int i = 0; i < changes.length; i++)
-         {
-            PropertyChange change = changes[i];
-            String key = change.getKey();
-            int type = change.getType();
-
-            // If the original value exist and is read only we perform a reset instead
-            PreferenceInfo pref = prefs.getPreference(key);
-            if (pref != null)
-            {
-               if (Boolean.TRUE.equals(pref.isReadOnly()))
-               {
-                  type = PropertyChange.PREF_RESET;
-               }
-            }
-
-            //
-            if (type == PropertyChange.PREF_UPDATE)
-            {
-               properties.setProperty(key, change.getValue());
-            }
-            else
-            {
-               properties.remove(key);
-            }
-         }
-//
-//         //  Remove read only values
-//         for (Iterator i = new ArrayList(properties.keySet()).iterator();i.hasNext();)
-//         {
-//            String key = (String)i.next();
-//            Value value = properties.getProperty(key);
-//            PreferenceInfo pref = prefs.getPreference(key);
-//            if (pref != null)
-//            {
-//               if (Boolean.TRUE.equals(pref.isReadOnly()))
-//               {
-//                  properties.setProperty(key, null);
-//               }
-//            }
-//         }
-
-         //
-         stateStore.updateState(stateId, properties);
-      }
-      catch (NoSuchStateException e)
-      {
-         throw new NoSuchPortletException(e, portletId);
-      }
-      catch (InvalidStateIdException e)
-      {
-         throw new InvalidPortletIdException(e, portletId);
-      }
-   }
-
-   /**
-    * Retrieve the properties from the portlet meta data.
-    *
-    * @param portletId the portlet id
-    * @return the properties
-    * @throws PortletInvokerException
-    */
-   private PropertyMap getPropertiesFromMetaData(String portletId) throws PortletInvokerException
-   {
-      //
-      Portlet portlet = portletInvoker.getPortlet(portletId);
-
-      // The prefs info
-      PreferencesInfo prefs = portlet.getInfo().getPreferences();
-
-      // Get the state
-      PropertyMap property = new SimplePropertyMap();
-      for (Iterator i = prefs.getKeys().iterator(); i.hasNext();)
-      {
-         String key = (String)i.next();
-         PreferenceInfo pref = prefs.getPreference(key);
-         property.setProperty(key, (Value)pref.getDefaultValue().clone());
-      }
-
-      //
-      return property;
-   }
-}

Copied: trunk/portlet/src/main/org/jboss/portal/portlet/stateful/PortletInvoker.java (from rev 5179, trunk/portlet/src/main/org/jboss/portal/portlet/PortletInvoker.java)
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/PortletInvoker.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/stateful/PortletInvoker.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,115 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.stateful;
+
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.state.PropertyChange;
+import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.Portlet;
+
+import java.util.Set;
+import java.util.List;
+
+/**
+ * The <code>PortletInvoker</code> is an abstraction for a set of portlets. It defines a context for performing
+ * operations are possible on a particular portlet among the set.
+ *
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision$
+ */
+public interface PortletInvoker
+{
+   /**
+    * Return the set of portlet exposed.
+    *
+    * @return the set of exposed portlets
+    */
+   Set getPortlets() throws PortletInvokerException;
+
+   /**
+    * Get information about a specific portlet.
+    *
+    * @param portletId the portlet identifier in the context of this invoker
+    * @return the <code>PortletInfo</code> for the specified portlet
+    * @throws IllegalArgumentException if the portletId is null
+    */
+   Portlet getPortlet(String portletId) throws IllegalArgumentException, PortletInvokerException;
+
+   /**
+    * Invoke an operation on a specific portlet.
+    *
+    * @param invocation the portlet invocation
+    * @throws IllegalArgumentException if the invocation is null
+    */
+   void invoke(PortletInvocation invocation) throws IllegalArgumentException, PortletInvokerException;
+
+   /**
+    * Clone a portlet.
+    *
+    * @return the clone id
+    * @throws IllegalArgumentException if the portletId is null
+    * @throws UnsupportedOperationException if the invoker does not support this operation
+    */
+   String createClone(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
+
+   /**
+    * Destroy a cloned portlet.
+    *
+    * @param portletIds a list of portlet ids to destroy
+    * @return a list of portlet ids that were not destroyed during the operation
+    * @throws IllegalArgumentException if the portletId is null
+    * @throws UnsupportedOperationException if the invoker does not support this operation
+    */
+   List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
+
+   /**
+    * Return a subset of the properties of the specified portlet.
+    *
+    * @param portletId the portlet id
+    * @param keys the set of keys to retrieve
+    * @return the properties
+    * @throws IllegalArgumentException if the portletId or the keys arguments are null
+    * @throws UnsupportedOperationException if the invoker does not support this operation
+    */
+   PropertyMap getProperties(String portletId, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
+
+   /**
+    * Return all the properties of the specified portlet.
+    *
+    * @param portletId the portlet id
+    * @return the properties
+    * @throws IllegalArgumentException if the portletId is null
+    * @throws UnsupportedOperationException if the invoker does not support this operation
+    */
+   PropertyMap getProperties(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
+
+   /**
+    * Set the properties on the specified portlet.
+    *
+    * @param portletId  the portlet id
+    * @param changes the changes
+    * @throws IllegalArgumentException if the portletId or the properties is null
+    * @throws UnsupportedOperationException if the invoker does not support this operation
+    */
+   void setProperties(String portletId, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException;
+}


Property changes on: trunk/portlet/src/main/org/jboss/portal/portlet/stateful/PortletInvoker.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/support/spi/InstanceContextSupport.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/support/spi/InstanceContextSupport.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/support/spi/InstanceContextSupport.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -23,6 +23,7 @@
 
 import org.jboss.portal.portlet.spi.InstanceContext;
 import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.StateEvent;
 
 /**
  * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
@@ -35,18 +36,13 @@
       throw new UnsupportedOperationException();
    }
 
-   public void portletCloned(String cloneId)
+   public AccessMode getAccessMode()
    {
       throw new UnsupportedOperationException();
    }
 
-   public void portletCloned(byte[] state)
+   public void onStateEvent(StateEvent event)
    {
       throw new UnsupportedOperationException();
    }
-
-   public AccessMode getAccessMode()
-   {
-      throw new UnsupportedOperationException();
-   }
 }

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/support/spi/PortletInvocationContextSupport.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/support/spi/PortletInvocationContextSupport.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/support/spi/PortletInvocationContextSupport.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -26,15 +26,14 @@
 import org.jboss.portal.portlet.PortletURL;
 import org.jboss.portal.Mode;
 import org.jboss.portal.WindowState;
-import org.jboss.portal.common.invocation.Scope;
-import org.jboss.portal.common.invocation.AttributeResolver;
+import org.jboss.portal.common.invocation.AbstractInvocationContext;
 import org.jboss.portal.server.util.HTTPStreamInfo;
 
 /**
  * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
  * @version $Revision: 5064 $
  */
-public class PortletInvocationContextSupport implements PortletInvocationContext
+public class PortletInvocationContextSupport extends AbstractInvocationContext implements PortletInvocationContext
 {
 
    public StateString getNavigationalState()
@@ -66,24 +65,4 @@
    {
       throw new UnsupportedOperationException();
    }
-
-   public void setAttribute(Scope scope, String name, Object value)
-   {
-      throw new UnsupportedOperationException();
-   }
-
-   public Object getAttribute(Scope scope, String name)
-   {
-      throw new UnsupportedOperationException();
-   }
-
-   public AttributeResolver getAttributeResolver(Scope attrScope) throws IllegalArgumentException
-   {
-      throw new UnsupportedOperationException();
-   }
-
-   public void removeAttribute(Scope attrScope, String attrName)
-   {
-      throw new UnsupportedOperationException();
-   }
 }

Added: trunk/portlet/src/main/org/jboss/portal/portlet/test/ActionContextImpl.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/test/ActionContextImpl.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/test/ActionContextImpl.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,54 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.test;
+
+import org.jboss.portal.portlet.support.spi.ActionContextSupport;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+import org.jboss.portal.Mode;
+import org.jboss.portal.server.impl.MapAttributeResolver;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 5113 $
+ */
+public class ActionContextImpl extends ActionContextSupport
+{
+
+   /** . */
+   private final Mode mode;
+
+   public ActionContextImpl(Mode mode)
+   {
+      this.mode = mode;
+      addResolver(PortletInvocation.REQUEST_SCOPE, new MapAttributeResolver());
+   }
+
+   public ActionContextImpl()
+   {
+      this(Mode.EDIT);
+   }
+
+   public Mode getMode()
+   {
+      return mode;
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/portlet/test/InstanceContextImpl.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/test/InstanceContextImpl.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/test/InstanceContextImpl.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,76 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.test;
+
+import org.jboss.portal.portlet.spi.InstanceContext;
+import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.StateEvent;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class InstanceContextImpl implements InstanceContext
+{
+
+   /** . */
+   private final String id;
+
+   /** . */
+   private final AccessMode accessMode;
+
+   public InstanceContextImpl(String id)
+   {
+      this(id, AccessMode.READ_ONLY);
+   }
+
+   public InstanceContextImpl(String id, AccessMode accessMode)
+   {
+      if (id == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (accessMode == null)
+      {
+         throw new IllegalArgumentException();
+      }
+
+      //
+      this.id = id;
+      this.accessMode = accessMode;
+   }
+
+   public String getId()
+   {
+      return id;
+   }
+
+   public AccessMode getAccessMode()
+   {
+      return accessMode;
+   }
+
+   public void onStateEvent(StateEvent event)
+   {
+      // No op
+   }
+}

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/test/PortletController.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/test/PortletController.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/test/PortletController.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -23,6 +23,7 @@
 
 import org.jboss.portal.Mode;
 import org.jboss.portal.WindowState;
+import org.jboss.portal.test.framework.container.TestCaseContext;
 import org.jboss.portal.jems.as.system.AbstractJBossService;
 import org.jboss.portal.common.util.Tools;
 import org.jboss.portal.common.util.URLTools;
@@ -30,12 +31,14 @@
 import org.jboss.portal.portlet.Parameters;
 import org.jboss.portal.portlet.ParametersStateString;
 import org.jboss.portal.portlet.Portlet;
-import org.jboss.portal.portlet.PortletInvoker;
+import org.jboss.portal.portlet.stateful.PortletInvoker;
 import org.jboss.portal.portlet.PortletInvokerException;
 import org.jboss.portal.portlet.PortletRequestDecoder;
 import org.jboss.portal.portlet.PortletURL;
 import org.jboss.portal.portlet.RenderURL;
 import org.jboss.portal.portlet.StateString;
+import org.jboss.portal.portlet.StateEvent;
+import org.jboss.portal.portlet.PortletContext;
 import org.jboss.portal.portlet.impl.spi.AbstractPortletInvocationContext;
 import org.jboss.portal.portlet.impl.spi.AbstractRequestContext;
 import org.jboss.portal.portlet.impl.spi.AbstractSecurityContext;
@@ -58,6 +61,8 @@
 import org.jboss.portal.portlet.spi.UserContext;
 import org.jboss.portal.portlet.spi.WindowContext;
 import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.state.PortletClonedEvent;
+import org.jboss.portal.portlet.state.PortletModifiedEvent;
 import org.jboss.portal.server.AbstractServerURL;
 import org.jboss.portal.server.RequestController;
 import org.jboss.portal.server.ServerException;
@@ -115,6 +120,12 @@
 
    public void handle(ServerInvocation invocation) throws ServerException
    {
+      //
+      if (TestCaseContext.isCurrentRequestCount(0))
+      {
+         invocation.getServerContext().getClientRequest().getSession().invalidate();
+      }
+
       try
       {
          String requestPath = invocation.getServerContext().getPortalRequestPath();
@@ -142,7 +153,7 @@
                   decoder.getForm());
 
                ActionInvocation action = createAction(invocation, actionContext);
-               action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, ((InstanceContextImpl)action.getInstanceContext()).getPortletOrCloneId());
+               action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, ((InstanceContextImpl)action.getInstanceContext()).getPortletContext());
                portletInvoker.invoke(action);
                Result result = action.getResult();
                if (result instanceof RenderResult)
@@ -268,10 +279,17 @@
             PrintWriter writer = invocation.getServerContext().getClientResponse().getWriter();
 
             //
+            invocation.getServerContext().getClientRequest().getSession().getAttribute("CLONE_ON");
+
+            //
             writer.write("<div>");
             RenderInvocation render = createRender(invocation, renderContext);
-            render.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, ((InstanceContextImpl)render.getInstanceContext()).getPortletOrCloneId());
+            render.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, ((InstanceContextImpl)render.getInstanceContext()).getPortletContext());
             portletInvoker.invoke(render);
+
+            //
+
+
             Result result = render.getResult();
             if (result instanceof FragmentResult)
             {
@@ -374,33 +392,42 @@
    protected class InstanceContextImpl implements InstanceContext
    {
 
-      private String portletId;
       private HttpServletRequest req;
-      private String cloneId;
       private AccessMode accessMode;
+      private PortletContext portletContext;
+      private PortletContext cloneContext;
       private static final String CLONE_OF = "clone_of_";
 
       public InstanceContextImpl(Portlet portlet, HttpServletRequest req)
       {
-         this.portletId = portlet.getId();
+         this.portletContext = new PortletContext(portlet.getId());
          this.req = req;
-         this.cloneId = (String)req.getSession().getAttribute(CLONE_OF + portlet.getId());
-         this.accessMode = cloneId == null ? AccessMode.CLONE_BEFORE_WRITE : AccessMode.READ_WRITE;
+         this.cloneContext = (PortletContext)req.getSession().getAttribute(CLONE_OF + portlet.getId());
+         this.accessMode = cloneContext == null ? AccessMode.CLONE_BEFORE_WRITE : AccessMode.READ_WRITE;
       }
 
       public String getId()
       {
-         return portletId;
+         return portletContext.getId();
       }
 
-      public void portletCloned(String cloneId)
+      public void onStateEvent(StateEvent event)
       {
-         req.getSession().setAttribute(CLONE_OF + portletId, cloneId);
+         if (event instanceof PortletClonedEvent)
+         {
+            PortletClonedEvent pce = (PortletClonedEvent)event;
+            req.getSession().setAttribute(CLONE_OF + this.portletContext.getId(), pce.getClonedContext());
+         }
+         else if (event instanceof PortletModifiedEvent)
+         {
+            PortletModifiedEvent pme = (PortletModifiedEvent)event;
+            req.getSession().setAttribute(CLONE_OF + this.portletContext.getId(), pme.getModifiedContext());
+         }
       }
 
-      public void portletCloned(byte[] state)
+      public void portletCloned(String cloneId)
       {
-         throw new UnsupportedOperationException("NYI");
+         throw new UnsupportedOperationException();
       }
 
       public AccessMode getAccessMode()
@@ -408,9 +435,9 @@
          return accessMode;
       }
 
-      String getPortletOrCloneId()
+      public PortletContext getPortletContext()
       {
-         return cloneId != null ? cloneId : portletId;
+         return cloneContext != null ? cloneContext : portletContext;
       }
    }
 

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/test/TestPortletInvoker.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/test/TestPortletInvoker.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/test/TestPortletInvoker.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -25,11 +25,11 @@
 import org.jboss.portal.common.invocation.InvocationHandler;
 import org.jboss.portal.common.invocation.Invocation;
 import org.jboss.portal.common.invocation.InvocationException;
+import org.jboss.portal.portlet.Portlet;
+import org.jboss.portal.portlet.stateful.PortletInvoker;
+import org.jboss.portal.portlet.PortletInvokerException;
 import org.jboss.portal.portlet.state.PropertyMap;
 import org.jboss.portal.portlet.state.PropertyChange;
-import org.jboss.portal.portlet.Portlet;
-import org.jboss.portal.portlet.PortletInvoker;
-import org.jboss.portal.portlet.PortletInvokerException;
 import org.jboss.portal.portlet.invocation.PortletInvocation;
 import org.jboss.portal.jems.as.system.AbstractJBossService;
 
@@ -128,28 +128,28 @@
       }
    }
 
-   public String createClone(String portletId) throws PortletInvokerException
+   public String createClone(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      return producer.createClone(portletId);
+      throw new UnsupportedOperationException();
    }
 
    public List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      return producer.destroyClones(portletIds);
+      throw new UnsupportedOperationException();
    }
 
-   public PropertyMap getProperties(String portletId) throws PortletInvokerException
+   public PropertyMap getProperties(String portletId, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      return producer.getProperties(portletId);
+      throw new UnsupportedOperationException();
    }
 
-   public PropertyMap getProperties(String portletId, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   public PropertyMap getProperties(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      return producer.getProperties(portletId, keys);
+      throw new UnsupportedOperationException();
    }
 
    public void setProperties(String portletId, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      producer.setProperties(portletId, changes);
+      throw new UnsupportedOperationException();
    }
 }

Added: trunk/portlet/src/main/org/jboss/portal/portlet/test/UserContextImpl.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/test/UserContextImpl.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/test/UserContextImpl.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,54 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.test;
+
+import org.jboss.portal.portlet.support.spi.UserContextSupport;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 3188 $
+ */
+public class UserContextImpl extends UserContextSupport
+{
+
+   /** . */
+   private final String id;
+
+   public UserContextImpl(String id)
+   {
+      if (id == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      this.id = id;
+   }
+
+   public UserContextImpl()
+   {
+      this.id = null;
+   }
+
+   public String getId()
+   {
+      return id;
+   }
+}

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/test/support/PortletInvokerSupport.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/test/support/PortletInvokerSupport.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/test/support/PortletInvokerSupport.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -21,17 +21,15 @@
 */
 package org.jboss.portal.portlet.test.support;
 
-import org.jboss.portal.portlet.PortletInvoker;
+import org.jboss.portal.portlet.stateful.PortletInvoker;
 import org.jboss.portal.portlet.Portlet;
 import org.jboss.portal.portlet.PortletInvokerException;
 import org.jboss.portal.portlet.NoSuchPortletException;
 import org.jboss.portal.portlet.InvalidPortletIdException;
+import org.jboss.portal.portlet.test.support.info.PortletInfoSupport;
 import org.jboss.portal.portlet.state.PropertyMap;
-import org.jboss.portal.portlet.state.SimplePropertyMap;
 import org.jboss.portal.portlet.state.PropertyChange;
 import org.jboss.portal.portlet.info.PortletInfo;
-import org.jboss.portal.portlet.info.PreferencesInfo;
-import org.jboss.portal.portlet.info.PreferenceInfo;
 import org.jboss.portal.portlet.invocation.PortletInvocation;
 import org.jboss.portal.jems.as.system.AbstractJBossService;
 
@@ -39,7 +37,6 @@
 import java.util.HashMap;
 import java.util.Set;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -50,26 +47,56 @@
 {
 
    /** . */
-   private final Object invalidPortlet;
-
-   /** . */
    private Map portlets;
 
    public PortletInvokerSupport()
    {
-      invalidPortlet = new Object();
       this.portlets = new HashMap();
    }
 
-   public PortletInvokerSupport addPortlet(PortletSupport info)
+   public void setValid(String portletId, boolean valid)
    {
-      portlets.put(info.getId(), info);
+      if (portletId == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      InternalPortlet portlet = (InternalPortlet)portlets.get(portletId);
+      if (portlet == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      portlet.setValid(valid);
+   }
+
+   public PortletInvokerSupport addPortlet(String portletId, PortletInfoSupport info)
+   {
+      return addPortlet(portletId, new PortletSupport(info));
+   }
+
+   public PortletInvokerSupport addPortlet(String portletId, PortletSupport support)
+   {
+      if (portletId == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (support == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      InternalPortlet portlet = new InternalPortlet(portletId, support);
+      if (portlets.put(portlet.getId(), portlet) != null)
+      {
+         throw new IllegalStateException();
+      }
       return this;
    }
 
-   public PortletInvokerSupport addInvalidPortlet(String portletId)
+   public PortletInvokerSupport removePortlet(String portletId)
    {
-      portlets.put(portletId, invalidPortlet);
+      if (portlets.remove(portletId) == null)
+      {
+         throw new IllegalStateException();
+      }
       return this;
    }
 
@@ -86,67 +113,103 @@
    public void invoke(PortletInvocation invocation) throws PortletInvokerException
    {
       String portletId = (String)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE);
-      PortletSupport portlet = internalGetPortlet(portletId);
-      portlet.invoke(invocation);
+      InternalPortlet portlet = internalGetPortlet(portletId);
+      portlet.support.invoke(invocation);
    }
 
-   public PropertyMap getProperties(String portletId) throws PortletInvokerException
+   private InternalPortlet internalGetPortlet(String portletId) throws IllegalArgumentException, PortletInvokerException
    {
-      PortletSupport portlet = internalGetPortlet(portletId);
-      PortletInfo info = portlet.getInfo();
-      PropertyMap values = new SimplePropertyMap();
-      PreferencesInfo preferences = info.getPreferences();
-      for (Iterator i = preferences.getKeys().iterator(); i.hasNext();)
+      if (portletId == null)
       {
-         String key = (String)i.next();
-         PreferenceInfo preference = preferences.getPreference(key);
-         values.setProperty(key, preference.getDefaultValue());
+         throw new IllegalArgumentException();
       }
-      return values;
+      InternalPortlet portlet = (InternalPortlet)portlets.get(portletId);
+      if (portlet == null)
+      {
+         throw new NoSuchPortletException(portletId);
+      }
+      if (portlet.isValid() == false)
+      {
+         throw new InvalidPortletIdException(portletId);
+      }
+      return portlet;
    }
 
-   public PropertyMap getProperties(String portletId, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   private static class InternalPortlet implements Portlet
    {
-      PropertyMap props = getProperties(portletId);
-      props.keySet().removeAll(keys);
-      return props;
+
+      /** . */
+      private final String id;
+
+      /** . */
+      private final PortletSupport support;
+
+      /** . */
+      private boolean valid;
+
+      public InternalPortlet(String id, PortletSupport support)
+      {
+         if (id == null)
+         {
+            throw new IllegalArgumentException();
+         }
+         if (support == null)
+         {
+            throw new IllegalArgumentException();
+         }
+         this.id = id;
+         this.support = support;
+         this.valid = true;
+      }
+
+      public String getId()
+      {
+         return id;
+      }
+
+      public PortletInfo getInfo()
+      {
+         return support.getInfo();
+      }
+
+      public boolean isRemote()
+      {
+         return false;
+      }
+
+      public boolean isValid()
+      {
+         return valid;
+      }
+
+      public void setValid(boolean valid)
+      {
+         this.valid = valid;
+      }
    }
 
-   public String createClone(String portletId) throws NoSuchPortletException
+   public String createClone(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      throw new UnsupportedOperationException("Implement me");
+      throw new UnsupportedOperationException();
    }
 
-   public void destroyClone(String portletId)
+   public List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      throw new UnsupportedOperationException("Implement me");
+      throw new UnsupportedOperationException();
    }
 
-   public void setProperties(String portletId, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   public PropertyMap getProperties(String portletId, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      throw new UnsupportedOperationException("Implement me");
+      throw new UnsupportedOperationException();
    }
 
-   public List destroyClones(List portletIds) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   public PropertyMap getProperties(String portletId) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      throw new UnsupportedOperationException("Implement me");
+      throw new UnsupportedOperationException();
    }
 
-   private PortletSupport internalGetPortlet(String portletId) throws IllegalArgumentException, PortletInvokerException
+   public void setProperties(String portletId, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
-      if (portletId == null)
-      {
-         throw new IllegalArgumentException();
-      }
-      Object portlet = portlets.get(portletId);
-      if (portlet == invalidPortlet)
-      {
-         throw new InvalidPortletIdException(portletId);
-      }
-      if (portlet == null)
-      {
-         throw new NoSuchPortletException(portletId);
-      }
-      return (PortletSupport)portlet;
+      throw new UnsupportedOperationException();
    }
 }

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/test/support/PortletSupport.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/test/support/PortletSupport.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/test/support/PortletSupport.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -23,32 +23,36 @@
 
 import org.jboss.portal.portlet.Portlet;
 import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.test.support.info.PortletInfoSupport;
 import org.jboss.portal.portlet.invocation.PortletInvocation;
 import org.jboss.portal.portlet.info.PortletInfo;
-import org.jboss.portal.portlet.test.support.info.PortletInfoSupport;
 
 /**
  * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
  * @version $Revision$
  */
-public class PortletSupport implements Portlet
+public class PortletSupport
 {
 
    /** . */
-   protected final String id;
+   protected final PortletInfoSupport info;
 
    /** . */
-   protected final PortletInfoSupport info;
+   protected boolean valid;
 
-   public PortletSupport(String id)
+   public PortletSupport(PortletInfoSupport info)
    {
-      this.id = id;
-      this.info = new PortletInfoSupport();
+      if (info == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      this.info = info;
+      this.valid = true;
    }
 
-   public String getId()
+   public PortletSupport()
    {
-      return id;
+      this(new PortletInfoSupport());
    }
 
    public PortletInfo getInfo()
@@ -56,11 +60,6 @@
       return info;
    }
 
-   public boolean isRemote()
-   {
-      return false;
-   }
-
    public void invoke(PortletInvocation invocation) throws PortletInvokerException
    {
       throw new PortletInvokerException("No implementations");

Added: trunk/portlet/src/main/org/jboss/portal/portlet/test/support/info/MetaInfoSupport.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/test/support/info/MetaInfoSupport.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/test/support/info/MetaInfoSupport.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,77 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.portlet.test.support.info;
+
+import org.jboss.portal.portlet.info.MetaInfo;
+import org.jboss.portal.common.util.LocalizedString;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Locale;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class MetaInfoSupport implements MetaInfo
+{
+
+   /** . */
+   private Map values = new HashMap();
+
+   public LocalizedString getMetaValue(String key)
+   {
+      if (key == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      return (LocalizedString)values.get(key);
+   }
+
+   public void addValue(String key, Locale locale, String value)
+   {
+      if (key == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      LocalizedString string = new LocalizedString(value, locale);
+      if (values.put(key, string) != null)
+      {
+         throw new IllegalStateException();
+      }
+   }
+
+   public void setDisplayName(String name)
+   {
+      addValue(MetaInfo.DISPLAY_NAME, Locale.ENGLISH, name);
+   }
+
+   public String getDisplayName()
+   {
+      LocalizedString string = getMetaValue(MetaInfo.DISPLAY_NAME);
+      if (string == null)
+      {
+         throw new IllegalStateException();
+      }
+      return string.getString(Locale.ENGLISH, true);
+   }
+}

Modified: trunk/portlet/src/main/org/jboss/portal/portlet/test/support/info/PortletInfoSupport.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/portlet/test/support/info/PortletInfoSupport.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/portlet/test/support/info/PortletInfoSupport.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -41,6 +41,7 @@
    private SecurityInfoSupport securitySupport = new SecurityInfoSupport();
    private CacheInfoSupport cacheSupport = new CacheInfoSupport();
    private SessionInfoSupport sessionSupport = new SessionInfoSupport();
+   private MetaInfoSupport metaSupport = new MetaInfoSupport();
 
    public CapabilitiesInfo getCapabilities()
    {
@@ -59,9 +60,14 @@
 
    public MetaInfo getMeta()
    {
-      throw new UnsupportedOperationException("Implement me");
+      return metaSupport;
    }
 
+   public MetaInfoSupport getMetaSupport()
+   {
+      return metaSupport;
+   }
+
    public SecurityInfo getSecurity()
    {
       return securitySupport;

Added: trunk/portlet/src/main/org/jboss/portal/test/portlet/state/AbstractStatefulPortletInvokerTestCase.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/test/portlet/state/AbstractStatefulPortletInvokerTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/test/portlet/state/AbstractStatefulPortletInvokerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,784 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.test.portlet.state;
+
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.state.SimplePropertyMap;
+import org.jboss.portal.portlet.state.PropertyChange;
+import org.jboss.portal.portlet.state.DestroyCloneFailure;
+import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.state.AbstractPropertyContext;
+import org.jboss.portal.portlet.test.support.info.PortletInfoSupport;
+import org.jboss.portal.portlet.test.support.PortletSupport;
+import org.jboss.portal.portlet.test.ValueMapAssert;
+import org.jboss.portal.portlet.NoSuchPortletException;
+import org.jboss.portal.portlet.InvalidPortletIdException;
+import org.jboss.portal.portlet.Portlet;
+import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+import org.jboss.portal.portlet.invocation.ActionInvocation;
+import org.jboss.portal.portlet.info.MetaInfo;
+import org.jboss.portal.common.value.StringValue;
+import org.jboss.portal.common.util.LocalizedString;
+import org.jboss.portal.common.util.CollectionBuilder;
+
+import java.util.Locale;
+import java.util.List;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public abstract class AbstractStatefulPortletInvokerTestCase extends TestCase
+{
+
+   /**
+    *
+    */
+   protected abstract Portlet getPortlet(Object portletRef) throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract String getPortletId(Object portletRef) throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract Object createPOPRef(PortletSupport portletSupport) throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract Object createNonExistingPOPRef() throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract Object createInvalidPOPRef() throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract Object createLocalClone(Object portletRef) throws Exception;
+
+   /**
+    *
+    */
+   protected abstract void destroyClone(Object portletRef) throws Exception;
+
+   /**
+    *
+    */
+   protected abstract Object createClone(Object portletRef) throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract Object setProperties(Object portletRef, PropertyChange[] changes) throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract PropertyMap getProperties(Object portletRef) throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract PropertyMap getProperties(Object portletRef, Set keys) throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract List destroyClones(List portletRefs) throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract void assertNoExistingState();
+
+   /**
+    *
+    */
+   protected abstract void invoke(PortletInvocation invocation) throws PortletInvokerException;
+
+   /**
+    *
+    */
+   protected abstract ActionInvocation createAction(Object portletRef, AccessMode accessMode);
+
+   /**
+    *
+    */
+   protected abstract Object getImplicitClonedRef(ActionInvocation action);
+
+   /**
+    *
+    */
+   protected abstract Object getModifiedPortletRef(ActionInvocation action);
+
+   /**
+    *
+    */
+   protected final Object createPOPRef(PortletInfoSupport portletInfo) throws PortletInvokerException
+   {
+      PortletSupport portletSupport = new PortletSupport(portletInfo);
+      return createPOPRef(portletSupport);
+   }
+
+   /**
+    *
+    */
+   protected final Object createLocalCCPRef() throws Exception
+   {
+      Object popCtx = createPOPRef();
+      return createLocalClone(popCtx);
+   }
+
+   /**
+    *
+    */
+   protected final Object createNonExistingLocalCCPRef() throws Exception
+   {
+      Object popRef = createPOPRef();
+      Object ccpRef = createLocalClone(popRef);
+      destroyClone(ccpRef);
+      return ccpRef;
+   }
+
+   /**
+    *
+    */
+   protected final Object createPOPRef() throws PortletInvokerException
+   {
+      PortletInfoSupport info = new PortletInfoSupport();
+      return createPOPRef(info);
+   }
+
+   public void testCloneWithNullContext() throws Exception
+   {
+      try
+      {
+         createClone(null);
+         fail("was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException expected)
+      {
+      }
+      assertNoExistingState();
+   }
+
+   public void testCloneNonExistingPOP() throws Exception
+   {
+      Object popCtx = createNonExistingPOPRef();
+      try
+      {
+         createClone(popCtx);
+         fail("was expecting an NoSuchPortletException");
+      }
+      catch (NoSuchPortletException expected)
+      {
+      }
+      assertNoExistingState();
+   }
+
+   public void testCloneNonExistingCCP() throws Exception
+   {
+      Object ccpCtx = createNonExistingLocalCCPRef();
+      try
+      {
+         createClone(ccpCtx);
+         fail("was expecting an NoSuchPortletException");
+      }
+      catch (NoSuchPortletException expected)
+      {
+      }
+      assertNoExistingState();
+   }
+
+//   public void testCloneInvalidCCP() throws Exception
+//   {
+//      PortletContext ccpCtx = getProducer().wrapCCP("InvalidPortletId");
+//      try
+//      {
+//         getProducer().createClone(ccpCtx);
+//         fail("was expecting an InvalidPortletIdException");
+//      }
+//      catch (InvalidPortletIdException expected)
+//      {
+//      }
+//      assertNoExistingState();
+//   }
+
+   public void testCloneInvalidPOP() throws Exception
+   {
+      Object popCtx = createInvalidPOPRef();
+      try
+      {
+         createClone(popCtx);
+         fail("was expecting an InvalidPortletIdException");
+      }
+      catch (InvalidPortletIdException expected)
+      {
+      }
+      assertNoExistingState();
+   }
+
+   public void testClonePortlet() throws Exception
+   {
+      PortletInfoSupport info = new PortletInfoSupport();
+      info.getMetaSupport().setDisplayName("MyPortlet");
+      info.getPreferencesSupport().addPreference("abc", new StringValue("def"));
+
+      Object popCtx = createPOPRef(info);
+      Object ccp1Ctx = createClone(popCtx);
+
+      // Check state
+      PropertyMap expected = new SimplePropertyMap();
+      expected.setProperty("abc", new StringValue("def"));
+      PropertyMap ccp1Props = getProperties(ccp1Ctx);
+      ValueMapAssert.assertEquals(expected, ccp1Props);
+
+      //
+      Portlet ccp1 = getPortlet(ccp1Ctx);
+      LocalizedString abc = ccp1.getInfo().getMeta().getMetaValue(MetaInfo.DISPLAY_NAME);
+      assertEquals("MyPortlet", abc.getString(Locale.ENGLISH, true));
+
+      // Update state
+      PropertyChange[] changes = new PropertyChange[]{PropertyChange.newUpdate("ghi", new StringValue("jkl"))};
+      ccp1Ctx = setProperties(ccp1Ctx, changes);
+
+      // Clone a CCP
+      Object ccp2Ctx = createClone(ccp1Ctx);
+
+      // Check state
+      expected = new SimplePropertyMap();
+      expected.setProperty("abc", new StringValue("def"));
+      expected.setProperty("ghi", new StringValue("jkl"));
+      PropertyMap ccp2Props = getProperties(ccp2Ctx);
+      ValueMapAssert.assertEquals(expected, ccp2Props);
+
+      //
+      Portlet ccp2 = getPortlet(ccp2Ctx);
+      LocalizedString def = ccp2.getInfo().getMeta().getMetaValue(MetaInfo.DISPLAY_NAME);
+      assertEquals("MyPortlet", def.getString(Locale.ENGLISH, true));
+   }
+
+   public void testGetWithNullId() throws Exception
+   {
+      try
+      {
+         getPortlet(null);
+         fail("was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException expected)
+      {
+      }
+   }
+
+   public void testGetNonExistingPOP() throws Exception
+   {
+      Object pop = createNonExistingPOPRef();
+      try
+      {
+         getPortlet(pop);
+         fail("was expecting a NoSuchPortletException");
+      }
+      catch (NoSuchPortletException expected)
+      {
+      }
+   }
+
+   public void testGetNonExistingCCP() throws Exception
+   {
+      Object ccpCtx = createNonExistingLocalCCPRef();
+      try
+      {
+         getPortlet(ccpCtx);
+         fail("was expecting a NoSuchPortletException");
+      }
+      catch (NoSuchPortletException expected)
+      {
+      }
+   }
+
+   public void testGetInvalidPOP() throws Exception
+   {
+      Object popCtx = createInvalidPOPRef();
+      try
+      {
+         getPortlet(popCtx);
+         fail("was expecting an InvalidPortletIdException");
+      }
+      catch (InvalidPortletIdException expected)
+      {
+      }
+   }
+
+//   public void testGetInvalidCCP() throws Exception
+//   {
+//      PortletContext ccpId = getProducer().wrapCCP("InvalidPortletId");
+//      try
+//      {
+//         getProducer().getPortlet(ccpId.getId());
+//         fail("was expecting an InvalidPortletIdException");
+//      }
+//      catch (InvalidPortletIdException expected)
+//      {
+//      }
+//   }
+
+   public void testDestroyWithNullId() throws Exception
+   {
+      try
+      {
+         destroyClones(null);
+         fail("was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException expected)
+      {
+      }
+   }
+
+   public void testDestroyPOP() throws Exception
+   {
+      Object popCtx = createPOPRef();
+      List failures = destroyClones(Collections.singletonList(popCtx));
+      assertEquals(1, failures.size());
+      DestroyCloneFailure failure = (DestroyCloneFailure)failures.get(0);
+      assertEquals(getPortletId(popCtx), failure.getPortletId());
+   }
+
+   public void testDestroyCCP() throws Exception
+   {
+      Object popCtx = createPOPRef();
+      Object ccpCtx = createClone(popCtx);
+      List failures = destroyClones(Collections.singletonList(ccpCtx));
+      assertEquals(0, failures.size());
+      assertNoExistingState();
+   }
+
+//   public void testDestroyInvalidCCP() throws Exception
+//   {
+//      PortletContext ccpId = getProducer().wrapCCP("PortletId");
+//      List failures = getProducer().destroyClones(Collections.singletonList(ccpId));
+//      assertEquals(1, failures.size());
+//      DestroyCloneFailure failure = (DestroyCloneFailure)failures.get(0);
+//      assertEquals(ccpId.getId(), failure.getPortletId());
+//   }
+
+   public void testDestroyNonExistingCCP() throws Exception
+   {
+      Object ccpCtx = createNonExistingLocalCCPRef();
+      List failures = destroyClones(Collections.singletonList(ccpCtx));
+      assertEquals(1, failures.size());
+      DestroyCloneFailure failure = (DestroyCloneFailure)failures.get(0);
+      assertEquals(getPortletId(ccpCtx), failure.getPortletId());
+   }
+
+   public void testGetPropertiesWithNullPortlet() throws Exception
+   {
+      try
+      {
+         getProperties(null);
+         fail("was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException e)
+      {
+      }
+      try
+      {
+         getProperties(null, new HashSet());
+         fail("was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException e)
+      {
+      }
+   }
+
+   public void testGetNonExistingPOPProperties() throws Exception
+   {
+      Object popCtx = createNonExistingPOPRef();
+      try
+      {
+         getProperties(popCtx);
+         fail("was expecting a NoSuchPortletException");
+      }
+      catch (NoSuchPortletException e)
+      {
+      }
+      try
+      {
+         getProperties(popCtx, new HashSet());
+         fail("was expecting a NoSuchPortletException");
+      }
+      catch (NoSuchPortletException e)
+      {
+      }
+   }
+
+   public void testGetInvalidPOPProperties() throws Exception
+   {
+      Object popCtx = createInvalidPOPRef();
+      try
+      {
+         getProperties(popCtx);
+         fail("was expecting an InvalidPortletIdException");
+      }
+      catch (InvalidPortletIdException e)
+      {
+      }
+      try
+      {
+         getProperties(popCtx, new HashSet());
+         fail("was expecting an InvalidPortletIdException");
+      }
+      catch (InvalidPortletIdException e)
+      {
+      }
+   }
+
+   public void testGetNonExistingCCPProperties() throws Exception
+   {
+      Object ccpCtx = createNonExistingLocalCCPRef();
+      try
+      {
+         getProperties(ccpCtx);
+         fail("was expecting a NoSuchPortletException");
+      }
+      catch (NoSuchPortletException e)
+      {
+      }
+      try
+      {
+         getProperties(ccpCtx, new HashSet());
+         fail("was expecting a NoSuchPortletException");
+      }
+      catch (NoSuchPortletException e)
+      {
+      }
+   }
+
+//   public void testGetInvalidCCPProperties() throws Exception
+//   {
+//      PortletContext ccpId = getProducer().wrapCCP("InvalidPortletId");
+//      try
+//      {
+//         getProducer().getProperties(ccpId);
+//         fail("was expecting a nInvalidPortletIdException");
+//      }
+//      catch (InvalidPortletIdException e)
+//      {
+//      }
+//      try
+//      {
+//         getProducer().getProperties(ccpId, new HashSet());
+//         fail("was expecting a nInvalidPortletIdException");
+//      }
+//      catch (InvalidPortletIdException e)
+//      {
+//      }
+//   }
+
+   public void testGetPOPWithNullKeys() throws Exception
+   {
+      Object popCtx = createPOPRef();
+      try
+      {
+         getProperties(popCtx, null);
+         fail("was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException e)
+      {
+      }
+   }
+
+   public void testGetCCPWithNullKeys() throws Exception
+   {
+      Object ccpCtx = createLocalCCPRef();
+      try
+      {
+         getProperties(ccpCtx, null);
+         fail("was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException e)
+      {
+      }
+   }
+
+   public void testGetPOPProperties() throws Exception
+   {
+      PortletInfoSupport info = new PortletInfoSupport();
+      info.getPreferencesSupport().addPreference("abc", new StringValue("def"));
+      info.getPreferencesSupport().addPreference("ghi", new StringValue("jkl"), Boolean.TRUE);
+      Object popCtx = createPOPRef(info);
+
+      //
+      PropertyMap props = getProperties(popCtx);
+      PropertyMap expectedProps = new SimplePropertyMap();
+      expectedProps.setProperty("abc", new StringValue("def"));
+      expectedProps.setProperty("ghi", new StringValue("jkl"));
+      ValueMapAssert.assertEquals(expectedProps, props);
+
+      //
+      props = getProperties(popCtx, new CollectionBuilder().add("abc").add("mno").toHashSet());
+      expectedProps = new SimplePropertyMap();
+      expectedProps.setProperty("abc", new StringValue("def"));
+      ValueMapAssert.assertEquals(expectedProps, props);
+   }
+
+   public void testGetCCPProperties() throws Exception
+   {
+      PortletInfoSupport info = new PortletInfoSupport();
+      info.getPreferencesSupport().addPreference("abc", new StringValue("def"));
+      info.getPreferencesSupport().addPreference("ghi", new StringValue("jkl"));
+      info.getPreferencesSupport().addPreference("mno", new StringValue("pqr"), Boolean.TRUE);
+      info.getPreferencesSupport().addPreference("stu", new StringValue("vwx"), Boolean.TRUE);
+      Object popCtx = createPOPRef(info);
+
+      //
+      Object ccpCtx = createClone(popCtx);
+      ccpCtx = setProperties(ccpCtx, new PropertyChange[]{
+         PropertyChange.newUpdate("abc", new StringValue("_def")),
+         PropertyChange.newReset("gho"),
+         PropertyChange.newUpdate("mno", new StringValue("_pqr")),
+         PropertyChange.newReset("stu")});
+
+      //
+      PropertyMap props = getProperties(ccpCtx);
+      PropertyMap expectedProps = new SimplePropertyMap();
+      expectedProps.setProperty("abc", new StringValue("_def"));
+      expectedProps.setProperty("ghi", new StringValue("jkl"));
+      expectedProps.setProperty("mno", new StringValue("pqr"));
+      expectedProps.setProperty("stu", new StringValue("vwx"));
+      ValueMapAssert.assertEquals(expectedProps, props);
+
+      //
+      props = getProperties(ccpCtx, new CollectionBuilder().add("abc").add("mno").add("yz").toHashSet());
+      expectedProps = new SimplePropertyMap();
+      expectedProps.setProperty("abc", new StringValue("_def"));
+      expectedProps.setProperty("mno", new StringValue("pqr"));
+      ValueMapAssert.assertEquals(expectedProps, props);
+   }
+
+   public void testSetPropertiesWithNullId() throws Exception
+   {
+      try
+      {
+         setProperties(null, new PropertyChange[0]);
+         fail("Was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException expected)
+      {
+      }
+   }
+
+   public void testSetPropertiesWithNullProperties() throws Exception
+   {
+      Object ccpCtx = createLocalCCPRef();
+      try
+      {
+         setProperties(ccpCtx, null);
+         fail("Was expecting an IllegalArgumentException");
+      }
+      catch (IllegalArgumentException expected)
+      {
+      }
+   }
+
+   public void testSetPOPProperties() throws Exception
+   {
+      Object popCtx = createPOPRef();
+      try
+      {
+         setProperties(popCtx, new PropertyChange[0]);
+         fail("Was expecting an InvalidPortletIdException");
+      }
+      catch (InvalidPortletIdException expected)
+      {
+      }
+   }
+
+   public void testSetNonExistingCCPProperties() throws Exception
+   {
+      Object ccpCtx = createNonExistingLocalCCPRef();
+      try
+      {
+         setProperties(ccpCtx, new PropertyChange[0]);
+         fail("Was expecting a NoSuchPortletException");
+      }
+      catch (NoSuchPortletException expected)
+      {
+      }
+   }
+
+   public void testSetCCPProperties() throws Exception
+   {
+      PortletInfoSupport info = new PortletInfoSupport();
+      info.getPreferencesSupport().addPreference("override_update", new StringValue("override_update_portlet_value"));
+      info.getPreferencesSupport().addPreference("override_reset", new StringValue("override_reset_portlet_value"));
+      info.getPreferencesSupport().addPreference("override_create", new StringValue("override_create_portlet_value"));
+      info.getPreferencesSupport().addPreference("readonly_create", new StringValue("readonly_create_portlet_value"), Boolean.TRUE);
+      Object popCtx = createPOPRef(info);
+
+      //
+      Object ccpCtx = createClone(popCtx);
+      ccpCtx = setProperties(ccpCtx, new PropertyChange[]{
+        PropertyChange.newUpdate("override_update", new StringValue("override_update_clone_value")),
+        PropertyChange.newUpdate("override_reset", new StringValue("override_reset_clone_value")),
+        PropertyChange.newUpdate("dynamic_update", new StringValue("dynamic_update_clone_value")),
+        PropertyChange.newUpdate("dynamic_reset", new StringValue("dynamic_reset_clone_value")),
+      });
+
+      //
+      PropertyMap expectedProps = new SimplePropertyMap();
+      expectedProps.setProperty("override_update", new StringValue("override_update_clone_value"));
+      expectedProps.setProperty("override_reset", new StringValue("override_reset_clone_value"));
+      expectedProps.setProperty("override_create", new StringValue("override_create_portlet_value"));
+      expectedProps.setProperty("readonly_create", new StringValue("readonly_create_portlet_value"));
+      expectedProps.setProperty("dynamic_update", new StringValue("dynamic_update_clone_value"));
+      expectedProps.setProperty("dynamic_reset", new StringValue("dynamic_reset_clone_value"));
+      PropertyMap ccpProps = getProperties(ccpCtx);
+      ValueMapAssert.assertEquals(expectedProps, ccpProps);
+
+      //
+      PropertyChange[] changes = new PropertyChange[]
+      {
+         PropertyChange.newUpdate("override_update", new StringValue("override_update_clone_value_2")),
+         PropertyChange.newReset("override_reset"),
+         PropertyChange.newUpdate("override_create", new StringValue("override_create_clone_value_2")),
+         PropertyChange.newUpdate("dynamic_update", new StringValue("dynamic_update_clone_value_2")),
+         PropertyChange.newReset("dynamic_reset"),
+         PropertyChange.newUpdate("dynamic_create", new StringValue("dynamic_create_clone_value_2")),
+         PropertyChange.newUpdate("readonly_create", new StringValue("readonly_create_clone_value_2")),
+      };
+      ccpCtx = setProperties(ccpCtx, changes);
+
+      //
+      expectedProps.clear();
+      expectedProps.setProperty("override_update", new StringValue("override_update_clone_value_2"));
+      expectedProps.setProperty("override_create", new StringValue("override_create_clone_value_2"));
+      expectedProps.setProperty("override_reset", new StringValue("override_reset_portlet_value"));
+      expectedProps.setProperty("dynamic_update", new StringValue("dynamic_update_clone_value_2"));
+      expectedProps.setProperty("dynamic_create", new StringValue("dynamic_create_clone_value_2"));
+      expectedProps.setProperty("readonly_create", new StringValue("readonly_create_portlet_value"));
+      ccpProps = getProperties(ccpCtx);
+      ValueMapAssert.assertEquals(expectedProps, ccpProps);
+   }
+
+   public void testInvokeCloneBeforeWriteWithUpdate() throws Exception
+   {
+      PortletInfoSupport info = new PortletInfoSupport();
+      info.getPreferencesSupport().addPreference("abc", new StringValue("def"));
+      PortletSupport portletSupport = new PortletSupport(info)
+      {
+         public void invoke(PortletInvocation invocation)
+         {
+            AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
+            props.update(new PropertyChange[]{PropertyChange.newUpdate("abc", new StringValue("_def"))});
+         }
+      };
+      Object popCtx = createPOPRef(portletSupport);
+
+      //
+      ActionInvocation invocation = createAction(popCtx, AccessMode.CLONE_BEFORE_WRITE);
+      invoke(invocation);
+
+      //
+      Object cloneRef = getImplicitClonedRef(invocation);
+      assertNotNull(cloneRef);
+
+      //
+      PropertyMap blah = getProperties(cloneRef);
+      PropertyMap expectedProps = new SimplePropertyMap();
+      expectedProps.setProperty("abc", new StringValue("_def"));
+      ValueMapAssert.assertEquals(expectedProps, blah);
+   }
+
+   public void testInvokeReadOnlyWithUpdate() throws Exception
+   {
+      final Boolean[] ise = {Boolean.FALSE};
+
+      PortletInfoSupport info = new PortletInfoSupport();
+      info.getPreferencesSupport().addPreference("abc", new StringValue("def"));
+      PortletSupport portletSupport = new PortletSupport(info)
+      {
+         public void invoke(PortletInvocation invocation)
+         {
+            try
+            {
+               AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
+               props.update(new PropertyChange[]{PropertyChange.newUpdate("abc", new StringValue("_def"))});
+            }
+            catch (IllegalStateException e)
+            {
+               ise[0] = Boolean.TRUE;
+            }
+         }
+      };
+      Object popCtx = createPOPRef(portletSupport);
+
+      //
+      ActionInvocation invocation = createAction(popCtx, AccessMode.READ_ONLY);
+      invoke(invocation);
+
+      //
+//      Object cloneRef = instanceCtx.getPortletRef();
+//      assertNull(cloneRef);
+      assertEquals(Boolean.TRUE, ise[0]);
+   }
+
+   public void testInvokeReadWriteWithUpdate() throws Exception
+   {
+      PortletInfoSupport info = new PortletInfoSupport();
+      info.getPreferencesSupport().addPreference("abc", new StringValue("def"));
+      PortletSupport portletSupport = new PortletSupport(info)
+      {
+         public void invoke(PortletInvocation invocation)
+         {
+            AbstractPropertyContext props = (AbstractPropertyContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PREFERENCES_ATTRIBUTE);
+            props.update(new PropertyChange[]{PropertyChange.newUpdate("abc", new StringValue("_def"))});
+         }
+      };
+      Object popCtx = createPOPRef(portletSupport);
+      Object ccpCtx = createClone(popCtx);
+
+      //
+      ActionInvocation invocation = createAction(ccpCtx, AccessMode.READ_WRITE);
+      invoke(invocation);
+
+      //
+      ccpCtx = getModifiedPortletRef(invocation);
+      assertNotNull(ccpCtx);
+
+      //
+      PropertyMap blah = getProperties(ccpCtx);
+      PropertyMap expectedProps = new SimplePropertyMap();
+      expectedProps.setProperty("abc", new StringValue("_def"));
+      ValueMapAssert.assertEquals(expectedProps, blah);
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/test/portlet/state/ConsumerStatefulPortletInvokerTestCase.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/test/portlet/state/ConsumerStatefulPortletInvokerTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/test/portlet/state/ConsumerStatefulPortletInvokerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,242 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.test.portlet.state;
+
+import org.jboss.portal.portlet.Portlet;
+import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.StateEvent;
+import org.jboss.portal.portlet.PortletClonedEvent;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+import org.jboss.portal.portlet.invocation.ActionInvocation;
+import org.jboss.portal.portlet.impl.state.producer.ProducerPersistenceManagerService;
+import org.jboss.portal.portlet.impl.state.StateManagementPolicyService;
+import org.jboss.portal.portlet.impl.state.StateConverterService;
+import org.jboss.portal.portlet.impl.state.consumer.ConsumerPersistenceManagerService;
+import org.jboss.portal.portlet.state.PropertyChange;
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.state.consumer.ConsumerPortletInvoker;
+import org.jboss.portal.portlet.state.producer.ProducerPortletInvoker;
+import org.jboss.portal.portlet.test.support.info.PortletInfoSupport;
+import org.jboss.portal.portlet.test.support.PortletInvokerSupport;
+import org.jboss.portal.portlet.test.support.PortletSupport;
+import org.jboss.portal.portlet.test.ActionContextImpl;
+import org.jboss.portal.portlet.test.InstanceContextImpl;
+
+import java.util.Set;
+import java.util.List;
+import java.util.Collections;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class ConsumerStatefulPortletInvokerTestCase extends AbstractStatefulPortletInvokerTestCase
+{
+
+   public ConsumerStatefulPortletInvokerTestCase(boolean persistLocally)
+   {
+      this.persistLocally = persistLocally;
+   }
+
+   /** . */
+   protected final boolean persistLocally;
+
+   /** . */
+   protected ConsumerPortletInvoker consumer;
+
+   /** . */
+   protected ConsumerPersistenceManagerService consumerPersistenceManager;
+
+   /** . */
+   protected ProducerPortletInvoker producer;
+
+   /** . */
+   protected PortletInvokerSupport container;
+
+   /** . */
+   protected ProducerPersistenceManagerService producerPersistenceManager;
+
+   /** . */
+   protected StateManagementPolicyService stateManagementPolicy;
+
+   /** . */
+   protected StateConverterService stateConverter;
+
+   protected void setUp() throws Exception
+   {
+      consumer = new ConsumerPortletInvoker();
+      consumerPersistenceManager = new ConsumerPersistenceManagerService();
+      producer = new ProducerPortletInvoker();
+      container = new PortletInvokerSupport();
+      producerPersistenceManager = new ProducerPersistenceManagerService();
+      stateManagementPolicy = new StateManagementPolicyService();
+      stateConverter = new StateConverterService();
+
+      //
+      stateManagementPolicy.setPersistLocally(persistLocally);
+
+      //
+      producer.setPortletInvoker(container);
+      producer.setPersistenceManager(producerPersistenceManager);
+      producer.setStateManagementPolicy(stateManagementPolicy);
+      producer.setStateConverter(stateConverter);
+
+      //
+      consumer.setPersistenceManager(consumerPersistenceManager);
+      consumer.setProducer(producer);
+   }
+
+   protected Portlet getPortlet(Object portletRef) throws PortletInvokerException
+   {
+      return consumer.getPortlet((String)portletRef);
+   }
+
+   protected Object createPOPRef(PortletSupport portletSupport) throws PortletInvokerException
+   {
+      container.addPortlet("PortletId", portletSupport);
+      Portlet portlet = getSinglePOP();
+      return portlet.getId();
+   }
+
+   protected Object createNonExistingPOPRef() throws PortletInvokerException
+   {
+      container.addPortlet("NonExistingPortletId", new PortletInfoSupport());
+      String popId = getSinglePOP().getId();
+      container.removePortlet("NonExistingPortletId");
+      return popId;
+   }
+
+   protected Object createInvalidPOPRef() throws PortletInvokerException
+   {
+      container.addPortlet("InvalidPortletId", new PortletInfoSupport());
+      String popId = getSinglePOP().getId();
+      container.setValid("InvalidPortletId", false);
+      return popId;
+   }
+
+   protected Object createLocalClone(Object portletRef) throws Exception
+   {
+      stateManagementPolicy.setPersistLocally(true);
+      String cloneRef = consumer.createClone((String)portletRef);
+      stateManagementPolicy.setPersistLocally(persistLocally);
+      return cloneRef;
+   }
+
+   protected void destroyClone(Object portletRef) throws Exception
+   {
+      assertEquals(Collections.EMPTY_LIST, consumer.destroyClones(Collections.singletonList(portletRef)));
+   }
+
+   protected void assertNoExistingState()
+   {
+      // todo
+   }
+
+   protected Object createClone(Object portletRef) throws PortletInvokerException
+   {
+      return consumer.createClone((String)portletRef);
+   }
+
+   protected Object setProperties(Object portletRef, PropertyChange[] changes) throws PortletInvokerException
+   {
+      consumer.setProperties((String)portletRef, changes);
+      return portletRef;
+   }
+
+   protected PropertyMap getProperties(Object portletRef) throws PortletInvokerException
+   {
+      return consumer.getProperties((String)portletRef);
+   }
+
+   protected PropertyMap getProperties(Object portletRef, Set keys) throws PortletInvokerException
+   {
+      return consumer.getProperties((String)portletRef, keys);
+   }
+
+   protected List destroyClones(List portletRefs) throws PortletInvokerException
+   {
+      return consumer.destroyClones(portletRefs);
+   }
+
+   protected String getPortletId(Object portletRef) throws PortletInvokerException
+   {
+      return (String)portletRef;
+   }
+
+   protected void invoke(PortletInvocation invocation) throws PortletInvokerException
+   {
+      consumer.invoke(invocation);
+   }
+
+   protected ActionInvocation createAction(Object portletRef, AccessMode accessMode)
+   {
+      ActionContextImpl actionCtx = new ActionContextImpl();
+      MyInstanceContext instanceCtx = new MyInstanceContext("blah", accessMode);
+
+      //
+      ActionInvocation action = new ActionInvocation(actionCtx);
+      action.setInstanceContext(instanceCtx);
+      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, portletRef);
+      return action;
+   }
+
+   protected Object getImplicitClonedRef(ActionInvocation action)
+   {
+      MyInstanceContext instanceCtx = (MyInstanceContext)action.getInstanceContext();
+      return instanceCtx.clonedId;
+   }
+
+   protected Object getModifiedPortletRef(ActionInvocation action)
+   {
+      return action.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE);
+   }
+
+   private Portlet getSinglePOP() throws PortletInvokerException
+   {
+      Set portlets = producer.getPortlets();
+      assertNotNull(portlets);
+      assertEquals(1, portlets.size());
+      return (Portlet)portlets.iterator().next();
+   }
+
+   public static class MyInstanceContext extends InstanceContextImpl
+   {
+
+      /** . */
+      protected String clonedId;
+
+      public MyInstanceContext(String id, AccessMode accessMode)
+      {
+         super(id, accessMode);
+      }
+
+      public void onStateEvent(StateEvent event)
+      {
+         if (event instanceof PortletClonedEvent)
+         {
+            PortletClonedEvent pce = (PortletClonedEvent)event;
+            clonedId = pce.getClonedId();
+         }
+      }
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/test/portlet/state/LocalStoreConsumerStatefulPortletInvokerTestCase.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/test/portlet/state/LocalStoreConsumerStatefulPortletInvokerTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/test/portlet/state/LocalStoreConsumerStatefulPortletInvokerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,34 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.test.portlet.state;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class LocalStoreConsumerStatefulPortletInvokerTestCase extends ConsumerStatefulPortletInvokerTestCase
+{
+   public LocalStoreConsumerStatefulPortletInvokerTestCase()
+   {
+      super(true);
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/test/portlet/state/LocalStoreProducerStatefulPortletInvokerTestCase.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/test/portlet/state/LocalStoreProducerStatefulPortletInvokerTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/test/portlet/state/LocalStoreProducerStatefulPortletInvokerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,42 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.test.portlet.state;
+
+import org.jboss.portal.portlet.invocation.ActionInvocation;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class LocalStoreProducerStatefulPortletInvokerTestCase extends ProducerStatefulPortletInvokerTestCase
+{
+   public LocalStoreProducerStatefulPortletInvokerTestCase()
+   {
+      super(true);
+   }
+
+   protected Object getModifiedPortletRef(ActionInvocation action)
+   {
+      return action.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE);
+   }
+}

Copied: trunk/portlet/src/main/org/jboss/portal/test/portlet/state/ProducerStatefulPortletInvokerTestCase.java (from rev 5145, trunk/portlet/src/main/org/jboss/portal/test/portlet/state/StatefulPortletInvokerTestCase.java)
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/test/portlet/state/StatefulPortletInvokerTestCase.java	2006-09-04 23:49:24 UTC (rev 5145)
+++ trunk/portlet/src/main/org/jboss/portal/test/portlet/state/ProducerStatefulPortletInvokerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,239 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.test.portlet.state;
+
+import org.jboss.portal.portlet.state.producer.ProducerPortletInvoker;
+import org.jboss.portal.portlet.PortletContext;
+import org.jboss.portal.portlet.state.PropertyChange;
+import org.jboss.portal.portlet.state.PropertyMap;
+import org.jboss.portal.portlet.state.AccessMode;
+import org.jboss.portal.portlet.state.PortletClonedEvent;
+import org.jboss.portal.portlet.state.PortletModifiedEvent;
+import org.jboss.portal.portlet.Portlet;
+import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.StateEvent;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
+import org.jboss.portal.portlet.invocation.ActionInvocation;
+import org.jboss.portal.portlet.impl.state.producer.ProducerPersistenceManagerService;
+import org.jboss.portal.portlet.impl.state.StateManagementPolicyService;
+import org.jboss.portal.portlet.impl.state.StateConverterService;
+import org.jboss.portal.portlet.test.support.PortletInvokerSupport;
+import org.jboss.portal.portlet.test.support.PortletSupport;
+import org.jboss.portal.portlet.test.support.info.PortletInfoSupport;
+import org.jboss.portal.portlet.test.ActionContextImpl;
+import org.jboss.portal.portlet.test.InstanceContextImpl;
+
+import java.util.Set;
+import java.util.List;
+import java.util.Collections;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision$
+ */
+public abstract class ProducerStatefulPortletInvokerTestCase extends AbstractStatefulPortletInvokerTestCase
+{
+
+   protected ProducerStatefulPortletInvokerTestCase(boolean persistLocally)
+   {
+      this.persistLocally = persistLocally;
+   }
+
+   /** . */
+   protected final boolean persistLocally;
+
+   /** . */
+   protected ProducerPortletInvoker producer;
+
+   /** . */
+   protected PortletInvokerSupport container;
+
+   /** . */
+   protected ProducerPersistenceManagerService persistenceManager;
+
+   /** . */
+   protected StateManagementPolicyService stateManagementPolicy;
+
+   /** . */
+   protected StateConverterService stateConverter;
+
+   protected void setUp() throws Exception
+   {
+      producer = new ProducerPortletInvoker();
+      container = new PortletInvokerSupport();
+      persistenceManager = new ProducerPersistenceManagerService();
+      stateManagementPolicy = new StateManagementPolicyService();
+      stateConverter = new StateConverterService();
+
+      //
+      stateManagementPolicy.setPersistLocally(persistLocally);
+
+      //
+      producer.setPortletInvoker(container);
+      producer.setPersistenceManager(persistenceManager);
+      producer.setStateManagementPolicy(stateManagementPolicy);
+      producer.setStateConverter(stateConverter);
+   }
+
+   protected void assertNoExistingState()
+   {
+      assertEquals(0, persistenceManager.getSize());
+   }
+
+   protected Object createPOPRef(PortletSupport portletSupport) throws PortletInvokerException
+   {
+      container.addPortlet("PortletId", portletSupport);
+      Portlet portlet = getSinglePOP();
+      return new PortletContext(portlet.getId());
+   }
+
+   protected Object createNonExistingPOPRef()
+   {
+      container.addPortlet("NonExistingPortletId", new PortletInfoSupport());
+      PortletContext popCtx = new PortletContext(getSinglePOP().getId());
+      container.removePortlet("NonExistingPortletId");
+      return popCtx;
+   }
+
+   protected Object createInvalidPOPRef()
+   {
+      container.addPortlet("InvalidPortletId", new PortletInfoSupport());
+      PortletContext popCtx = new PortletContext(getSinglePOP().getId());
+      container.setValid("InvalidPortletId", false);
+      return popCtx;
+   }
+
+   protected Object createLocalClone(Object portletRef) throws Exception
+   {
+      stateManagementPolicy.setPersistLocally(true);
+      PortletContext cloneContext = producer.createClone((PortletContext)portletRef);
+      stateManagementPolicy.setPersistLocally(persistLocally);
+      return cloneContext;
+   }
+
+   protected void destroyClone(Object portletRef) throws Exception
+   {
+      assertEquals(Collections.EMPTY_LIST, producer.destroyClones(Collections.singletonList(portletRef)));
+   }
+
+   protected Object createClone(Object portletRef) throws PortletInvokerException
+   {
+      return producer.createClone((PortletContext)portletRef);
+   }
+
+   protected Object setProperties(Object portletRef, PropertyChange[] changes) throws PortletInvokerException
+   {
+      return producer.setProperties((PortletContext)portletRef, changes);
+   }
+
+   protected PropertyMap getProperties(Object portletRef) throws PortletInvokerException
+   {
+      return producer.getProperties((PortletContext)portletRef);
+   }
+
+   protected PropertyMap getProperties(Object portletRef, Set keys) throws PortletInvokerException
+   {
+      return producer.getProperties((PortletContext)portletRef, keys);
+   }
+
+   protected List destroyClones(List portletRefs) throws PortletInvokerException
+   {
+      return producer.destroyClones(portletRefs);
+   }
+
+   protected Portlet getPortlet(Object portletRef) throws PortletInvokerException
+   {
+      if (portletRef == null)
+      {
+         return producer.getPortlet(null);
+      }
+      else
+      {
+         return producer.getPortlet(((PortletContext)portletRef).getId());
+      }
+   }
+
+   protected String getPortletId(Object portletRef) throws PortletInvokerException
+   {
+      return ((PortletContext)portletRef).getId();
+   }
+
+   protected void invoke(PortletInvocation invocation) throws PortletInvokerException
+   {
+      producer.invoke(invocation);
+   }
+
+   protected ActionInvocation createAction(Object portletRef, AccessMode accessMode)
+   {
+      ActionContextImpl actionCtx = new ActionContextImpl();
+      MyInstanceContext instanceCtx = new MyInstanceContext("blah", accessMode);
+
+      //
+      ActionInvocation action = new ActionInvocation(actionCtx);
+      action.setInstanceContext(instanceCtx);
+      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, portletRef);
+      return action;
+   }
+
+   protected Object getImplicitClonedRef(ActionInvocation action)
+   {
+      MyInstanceContext instanceCtx = (MyInstanceContext)action.getInstanceContext();
+      return instanceCtx.clonedContext;
+   }
+
+   private Portlet getSinglePOP()
+   {
+      Set portlets = container.getPortlets();
+      assertNotNull(portlets);
+      assertEquals(1, portlets.size());
+      return (Portlet)portlets.iterator().next();
+   }
+
+   public static class MyInstanceContext extends InstanceContextImpl
+   {
+
+      /** . */
+      protected PortletContext clonedContext;
+
+      /** . */
+      protected PortletContext modifiedContext;
+
+      public MyInstanceContext(String id, AccessMode accessMode)
+      {
+         super(id, accessMode);
+      }
+
+      public void onStateEvent(StateEvent event)
+      {
+         if (event instanceof PortletClonedEvent)
+         {
+            PortletClonedEvent pce = (PortletClonedEvent)event;
+            clonedContext = pce.getClonedContext();
+         }
+         else if (event instanceof PortletModifiedEvent)
+         {
+            PortletModifiedEvent pce = (PortletModifiedEvent)event;
+            clonedContext = pce.getModifiedContext();
+         }
+      }
+   }
+}


Property changes on: trunk/portlet/src/main/org/jboss/portal/test/portlet/state/ProducerStatefulPortletInvokerTestCase.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Added: trunk/portlet/src/main/org/jboss/portal/test/portlet/state/RemoteStoreConsumerStatefulPortletInvokerTestCase.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/test/portlet/state/RemoteStoreConsumerStatefulPortletInvokerTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/test/portlet/state/RemoteStoreConsumerStatefulPortletInvokerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,34 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.test.portlet.state;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class RemoteStoreConsumerStatefulPortletInvokerTestCase extends ConsumerStatefulPortletInvokerTestCase
+{
+   public RemoteStoreConsumerStatefulPortletInvokerTestCase()
+   {
+      super(false);
+   }
+}

Added: trunk/portlet/src/main/org/jboss/portal/test/portlet/state/RemoteStoreProducerStatefulPortletInvokerTestCase.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/test/portlet/state/RemoteStoreProducerStatefulPortletInvokerTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/test/portlet/state/RemoteStoreProducerStatefulPortletInvokerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,42 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.test.portlet.state;
+
+import org.jboss.portal.portlet.invocation.ActionInvocation;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class RemoteStoreProducerStatefulPortletInvokerTestCase extends ProducerStatefulPortletInvokerTestCase
+{
+   public RemoteStoreProducerStatefulPortletInvokerTestCase()
+   {
+      super(false);
+   }
+
+   protected Object getModifiedPortletRef(ActionInvocation action)
+   {
+      MyInstanceContext instanceCtx = (MyInstanceContext)action.getInstanceContext();
+      return instanceCtx.modifiedContext;
+   }
+}

Deleted: trunk/portlet/src/main/org/jboss/portal/test/portlet/state/StatefulPortletInvokerTestCase.java
===================================================================
--- trunk/portlet/src/main/org/jboss/portal/test/portlet/state/StatefulPortletInvokerTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/main/org/jboss/portal/test/portlet/state/StatefulPortletInvokerTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,595 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.test.portlet.state;
-
-import junit.framework.TestCase;
-import org.jboss.portal.portlet.state.producer.StatefulPortletInvoker;
-import org.jboss.portal.portlet.state.producer.State;
-import org.jboss.portal.portlet.state.producer.NoSuchStateException;
-import org.jboss.portal.portlet.state.producer.InvalidStateIdException;
-import org.jboss.portal.portlet.state.PropertyMap;
-import org.jboss.portal.portlet.state.SimplePropertyMap;
-import org.jboss.portal.portlet.state.PropertyChange;
-import org.jboss.portal.portlet.state.DestroyCloneFailure;
-import org.jboss.portal.portlet.NoSuchPortletException;
-import org.jboss.portal.portlet.InvalidPortletIdException;
-import org.jboss.portal.portlet.test.ValueMapAssert;
-import org.jboss.portal.portlet.test.support.PortletInvokerSupport;
-import org.jboss.portal.portlet.test.support.state.StateStoreSupport;
-import org.jboss.portal.portlet.test.support.PortletSupport;
-import org.jboss.portal.common.value.StringValue;
-import org.jboss.portal.common.util.CollectionBuilder;
-
-import java.util.HashSet;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision$
- */
-public class StatefulPortletInvokerTestCase extends TestCase
-{
-
-   private StatefulPortletInvoker invoker;
-   private PortletInvokerSupport nextInvoker;
-   private StateStoreSupport stateStore;
-
-   protected void setUp() throws Exception
-   {
-      invoker = new StatefulPortletInvoker();
-      nextInvoker = new PortletInvokerSupport();
-      stateStore = new StateStoreSupport();
-
-      //
-      invoker.setPortletInvoker(nextInvoker);
-      invoker.setStateStore(stateStore);
-   }
-
-   protected void tearDown() throws Exception
-   {
-      invoker = null;
-      nextInvoker = null;
-      stateStore = null;
-   }
-
-   public void testCloneWithNullId() throws Exception
-   {
-      try
-      {
-         invoker.createClone(null);
-         fail("was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException expected)
-      {
-      }
-   }
-
-   public void testCloneNonExistingPOP() throws Exception
-   {
-      String popId = invoker.wrapPOPId("NonExistingPortletId");
-      try
-      {
-         invoker.createClone(popId);
-         fail("was expecting an NoSuchPortletException");
-      }
-      catch (NoSuchPortletException expected)
-      {
-      }
-   }
-
-   public void testCloneNonExistingCCP() throws Exception
-   {
-      String ccpId = invoker.wrapCCPId("1");
-      try
-      {
-         invoker.createClone(ccpId);
-         fail("was expecting an NoSuchPortletException");
-      }
-      catch (NoSuchPortletException expected)
-      {
-      }
-   }
-
-   public void testCloneInvalidCCP() throws Exception
-   {
-      String ccpId = invoker.wrapCCPId("InvalidPortletId");
-      try
-      {
-         invoker.createClone(ccpId);
-         fail("was expecting an InvalidPortletIdException");
-      }
-      catch (InvalidPortletIdException expected)
-      {
-      }
-   }
-
-   public void testCloneInvalidPOP() throws Exception
-   {
-      nextInvoker.addInvalidPortlet("InvalidPortletId");
-      String popId = invoker.wrapPOPId("InvalidPortletId");
-      try
-      {
-         invoker.createClone(popId);
-         fail("was expecting an InvalidPortletIdException");
-      }
-      catch (InvalidPortletIdException expected)
-      {
-      }
-   }
-
-   public void testClonePortlet() throws Exception
-   {
-      nextInvoker.addPortlet(new PortletSupport("PortletId")
-      {
-         {
-            info.getPreferencesSupport().addPreference("abc", new StringValue("def"));
-         }
-      });
-      String popCloneId = invoker.createClone(invoker.wrapPOPId("PortletId"));
-
-      // Check state
-      assertNotNull(popCloneId);
-      String popCloneStateId = invoker.unwrapCCPId(popCloneId);
-      State popCloneState = stateStore.loadState(popCloneStateId);
-      assertNotNull(popCloneState);
-      assertEquals("PortletId", popCloneState.getPortletId());
-      PropertyMap expected = new SimplePropertyMap();
-      expected.setProperty("abc", new StringValue("def"));
-      ValueMapAssert.assertEquals(expected, popCloneState.getProperties());
-
-      // Update state
-      PropertyMap next = new SimplePropertyMap();
-      next.setProperty("ghi", new StringValue("jkl"));
-      stateStore.updateState(popCloneStateId, next);
-
-      // Clone a CCP
-      String ccpCloneId = invoker.createClone(popCloneId);
-
-      // Check state
-      assertNotNull(ccpCloneId);
-      String ccpCloneStateId = invoker.unwrapCCPId(ccpCloneId);
-      State ccpCloneState = stateStore.loadState(ccpCloneStateId);
-      assertNotNull(popCloneState);
-      assertEquals("PortletId", popCloneState.getPortletId());
-      expected = new SimplePropertyMap();
-      expected.setProperty("ghi", new StringValue("jkl"));
-      ValueMapAssert.assertEquals(expected, ccpCloneState.getProperties());
-   }
-
-   public void testGetWithNullId() throws Exception
-   {
-      try
-      {
-         invoker.getPortlet(null);
-         fail("was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException expected)
-      {
-      }
-   }
-
-   public void testGetNonExistingPOP() throws Exception
-   {
-      String popId = invoker.wrapPOPId("NonExistingPortletId");
-      try
-      {
-         invoker.getPortlet(popId);
-         fail("was expecting a NoSuchPortletException");
-      }
-      catch (NoSuchPortletException expected)
-      {
-      }
-   }
-
-   public void testGetNonExistingCCP() throws Exception
-   {
-      String ccpId = invoker.wrapCCPId("1");
-      try
-      {
-         invoker.getPortlet(ccpId);
-         fail("was expecting a NoSuchPortletException");
-      }
-      catch (NoSuchPortletException expected)
-      {
-      }
-   }
-
-   public void testGetInvalidPOP() throws Exception
-   {
-      nextInvoker.addInvalidPortlet("InvalidPortletId");
-      String popId = invoker.wrapPOPId("InvalidPortletId");
-      try
-      {
-         invoker.getPortlet(popId);
-         fail("was expecting an InvalidPortletIdException");
-      }
-      catch (InvalidPortletIdException expected)
-      {
-      }
-   }
-
-   public void testGetInvalidCCP() throws Exception
-   {
-      String ccpId = invoker.wrapCCPId("InvalidPortletId");
-      try
-      {
-         invoker.getPortlet(ccpId);
-         fail("was expecting an InvalidPortletIdException");
-      }
-      catch (InvalidPortletIdException expected)
-      {
-      }
-   }
-
-   public void testDestroyWithNullId() throws Exception
-   {
-      try
-      {
-         invoker.destroyClones(null);
-         fail("was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException expected)
-      {
-      }
-   }
-
-   public void testDestroyPOP() throws Exception
-   {
-      nextInvoker.addPortlet(new PortletSupport("PortletId"));
-      String popId = invoker.wrapPOPId("PortletId");
-      List failures = invoker.destroyClones(Collections.singletonList(popId));
-      assertEquals(1, failures.size());
-      DestroyCloneFailure failure = (DestroyCloneFailure)failures.get(0);
-      assertEquals("PortletId", failure.getPortletId());
-   }
-
-   public void testDestroyCCP() throws Exception
-   {
-      nextInvoker.addPortlet(new PortletSupport("PortletId"));
-      String stateId = stateStore.createState("PortletId", new SimplePropertyMap());
-      String cloneId = invoker.wrapCCPId(stateId);
-      List failures = invoker.destroyClones(Collections.singletonList(cloneId));
-      assertEquals(0, failures.size());
-      try
-      {
-         stateStore.loadState(stateId);
-         fail("Was expecting a NoSuchStateException");
-      }
-      catch (NoSuchStateException e)
-      {
-
-      }
-   }
-
-   public void testDestroyInvalidCCP() throws Exception
-   {
-      String ccpId = invoker.wrapCCPId("PortletId");
-      List failures = invoker.destroyClones(Collections.singletonList(ccpId));
-      assertEquals(1, failures.size());
-      DestroyCloneFailure failure = (DestroyCloneFailure)failures.get(0);
-      assertEquals(ccpId, failure.getPortletId());
-   }
-
-   public void testDestroyNonExistingCCP() throws Exception
-   {
-      String ccpId = invoker.wrapCCPId("1");
-      List failures = invoker.destroyClones(Collections.singletonList(ccpId));
-      assertEquals(1, failures.size());
-      DestroyCloneFailure failure = (DestroyCloneFailure)failures.get(0);
-      assertEquals(ccpId, failure.getPortletId());
-   }
-
-   public void testGetPropertiesWithNullPortlet() throws Exception
-   {
-      try
-      {
-         invoker.getProperties(null);
-         fail("was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException e)
-      {
-      }
-      try
-      {
-         invoker.getProperties(null, new HashSet());
-         fail("was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException e)
-      {
-      }
-   }
-
-   public void testGetNonExistingPOPProperties() throws Exception
-   {
-      String popId = invoker.wrapPOPId("NonExistingPortletId");
-      try
-      {
-         invoker.getProperties(popId);
-         fail("was expecting a NoSuchPortletException");
-      }
-      catch (NoSuchPortletException e)
-      {
-      }
-      try
-      {
-         invoker.getProperties(popId, new HashSet());
-         fail("was expecting a NoSuchPortletException");
-      }
-      catch (NoSuchPortletException e)
-      {
-      }
-   }
-
-   public void testGetInvalidPOPProperties() throws Exception
-   {
-      nextInvoker.addInvalidPortlet("InvalidPortletId");
-      String popId = invoker.wrapPOPId("InvalidPortletId");
-      try
-      {
-         invoker.getProperties(popId);
-         fail("was expecting an InvalidPortletIdException");
-      }
-      catch (InvalidPortletIdException e)
-      {
-      }
-      try
-      {
-         invoker.getProperties(popId, new HashSet());
-         fail("was expecting an InvalidPortletIdException");
-      }
-      catch (InvalidPortletIdException e)
-      {
-      }
-   }
-
-   public void testGetNonExistingCCPProperties() throws Exception
-   {
-      String ccpId = invoker.wrapCCPId("1");
-      try
-      {
-         invoker.getProperties(ccpId);
-         fail("was expecting a NoSuchPortletException");
-      }
-      catch (NoSuchPortletException e)
-      {
-      }
-      try
-      {
-         invoker.getProperties(ccpId, new HashSet());
-         fail("was expecting a NoSuchPortletException");
-      }
-      catch (NoSuchPortletException e)
-      {
-      }
-   }
-
-   public void testGetInvalidCCPProperties() throws Exception
-   {
-      String ccpId = invoker.wrapCCPId("InvalidPortletId");
-      try
-      {
-         invoker.getProperties(ccpId);
-         fail("was expecting a nInvalidPortletIdException");
-      }
-      catch (InvalidPortletIdException e)
-      {
-      }
-      try
-      {
-         invoker.getProperties(ccpId, new HashSet());
-         fail("was expecting a nInvalidPortletIdException");
-      }
-      catch (InvalidPortletIdException e)
-      {
-      }
-   }
-
-   public void testGetPOPWithNullKeys() throws Exception
-   {
-      nextInvoker.addPortlet(new PortletSupport("PortletId"));
-      String popId = invoker.wrapPOPId("PortletId");
-      try
-      {
-         invoker.getProperties(popId, null);
-         fail("was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException e)
-      {
-      }
-   }
-
-   public void testGetCCPWithNullKeys() throws Exception
-   {
-      nextInvoker.addPortlet(new PortletSupport("PortletId"));
-      PropertyMap ccpProps = new SimplePropertyMap();
-      String stateId = stateStore.createState("PortletId", ccpProps);
-      String ccpId = invoker.wrapCCPId(stateId);
-      try
-      {
-         invoker.getProperties(ccpId, null);
-         fail("was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException e)
-      {
-      }
-   }
-
-   public void testGetPOPProperties() throws Exception
-   {
-      nextInvoker.addPortlet(new PortletSupport("PortletId")
-      {
-         {
-            info.getPreferencesSupport().addPreference("abc", new StringValue("def"));
-            info.getPreferencesSupport().addPreference("ghi", new StringValue("jkl"), Boolean.TRUE);
-         }
-      });
-      String popId = invoker.wrapPOPId("PortletId");
-
-      //
-      PropertyMap props = invoker.getProperties(popId);
-      PropertyMap expectedProps = new SimplePropertyMap();
-      expectedProps.setProperty("abc", new StringValue("def"));
-      expectedProps.setProperty("ghi", new StringValue("jkl"));
-      ValueMapAssert.assertEquals(expectedProps, props);
-
-      //
-      props = invoker.getProperties(popId, new CollectionBuilder().add("abc").add("mno").toHashSet());
-      expectedProps = new SimplePropertyMap();
-      expectedProps.setProperty("abc", new StringValue("def"));
-      ValueMapAssert.assertEquals(expectedProps, props);
-   }
-
-   public void testGetCCPProperties() throws Exception
-   {
-      nextInvoker.addPortlet(new PortletSupport("PortletId")
-      {
-         {
-            info.getPreferencesSupport().addPreference("abc", new StringValue("def"));
-            info.getPreferencesSupport().addPreference("ghi", new StringValue("jkl"));
-            info.getPreferencesSupport().addPreference("mno", new StringValue("pqr"), Boolean.TRUE);
-            info.getPreferencesSupport().addPreference("stu", new StringValue("vwx"), Boolean.TRUE);
-         }
-      });
-      PropertyMap ccpProps = new SimplePropertyMap();
-      ccpProps.setProperty("abc", new StringValue("_def"));
-      ccpProps.setProperty("mno", new StringValue("_pqr"));
-      String stateId = stateStore.createState("PortletId", ccpProps);
-      String ccpId = invoker.wrapCCPId(stateId);
-
-      //
-      PropertyMap props = invoker.getProperties(ccpId);
-      PropertyMap expectedProps = new SimplePropertyMap();
-      expectedProps.setProperty("abc", new StringValue("_def"));
-      expectedProps.setProperty("ghi", new StringValue("jkl"));
-      expectedProps.setProperty("mno", new StringValue("pqr"));
-      expectedProps.setProperty("stu", new StringValue("vwx"));
-      ValueMapAssert.assertEquals(expectedProps, props);
-
-      //
-      props = invoker.getProperties(ccpId, new CollectionBuilder().add("abc").add("mno").add("yz").toHashSet());
-      expectedProps = new SimplePropertyMap();
-      expectedProps.setProperty("abc", new StringValue("_def"));
-      expectedProps.setProperty("mno", new StringValue("pqr"));
-      ValueMapAssert.assertEquals(expectedProps, props);
-   }
-
-   public void testSetPropertiesWithNullId() throws Exception
-   {
-      try
-      {
-         invoker.setProperties(null, new PropertyChange[0]);
-         fail("Was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException expected)
-      {
-      }
-   }
-
-   public void testSetPropertiesWithNullProperties() throws Exception
-   {
-      String ccpId = invoker.wrapCCPId("1");
-      try
-      {
-         invoker.setProperties(ccpId, null);
-         fail("Was expecting an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException expected)
-      {
-      }
-   }
-
-   public void testSetPOPProperties() throws Exception
-   {
-      nextInvoker.addPortlet(new PortletSupport("PortletId"));
-      String popId = invoker.wrapPOPId("PortletId");
-      try
-      {
-         invoker.setProperties(popId, new PropertyChange[0]);
-         fail("Was expecting an InvalidPortletIdException");
-      }
-      catch (InvalidPortletIdException expected)
-      {
-      }
-   }
-
-   public void testSetNonExistingCCPProperties() throws Exception
-   {
-      String ccpId = invoker.wrapCCPId("1");
-      try
-      {
-         invoker.setProperties(ccpId, new PropertyChange[0]);
-         fail("Was expecting a NoSuchPortletException");
-      }
-      catch (NoSuchPortletException expected)
-      {
-      }
-   }
-
-   public void testSetCCPProperties() throws Exception
-   {
-      SimplePropertyMap initialProps = new SimplePropertyMap();
-      initialProps.setProperty("override_update", new StringValue("override_update_clone_value"));
-      initialProps.setProperty("override_reset", new StringValue("override_reset_clone_value"));
-      initialProps.setProperty("dynamic_update", new StringValue("dynamic_update_clone_value"));
-      initialProps.setProperty("dynamic_reset", new StringValue("dynamic_reset_clone_value"));
-      String stateId = stateStore.createState("PortletId", initialProps);
-      nextInvoker.addPortlet(new PortletSupport("PortletId")
-      {
-         {
-            info.getPreferencesSupport().addPreference("override_update", new StringValue("override_update_portlet_value"));
-            info.getPreferencesSupport().addPreference("override_reset", new StringValue("override_reset_portlet_value"));
-            info.getPreferencesSupport().addPreference("override_create", new StringValue("override_create_portlet_value"));
-            info.getPreferencesSupport().addPreference("readonly_create", new StringValue("readonly_create_portlet_value"), Boolean.TRUE);
-         }
-      });
-      String ccpId = invoker.wrapCCPId(stateId);
-
-      //
-      PropertyChange[] changes = new PropertyChange[]
-      {
-         PropertyChange.newUpdate("override_update", new StringValue("override_update_clone_value_2")),
-         PropertyChange.newReset("override_reset"),
-         PropertyChange.newUpdate("override_create", new StringValue("override_create_clone_value_2")),
-         PropertyChange.newUpdate("dynamic_update", new StringValue("dynamic_update_clone_value_2")),
-         PropertyChange.newReset("dynamic_reset"),
-         PropertyChange.newUpdate("dynamic_create", new StringValue("dynamic_create_clone_value_2")),
-         PropertyChange.newUpdate("readonly_create", new StringValue("readonly_create_clone_value_2")),
-      };
-      invoker.setProperties(ccpId, changes);
-
-      //
-      State state = stateStore.loadState(stateId);
-      PropertyMap props = state.getProperties();
-      PropertyMap expectedProps = new SimplePropertyMap();
-      expectedProps.setProperty("override_update", new StringValue("override_update_clone_value_2"));
-      expectedProps.setProperty("override_create", new StringValue("override_create_clone_value_2"));
-      expectedProps.setProperty("dynamic_update", new StringValue("dynamic_update_clone_value_2"));
-      expectedProps.setProperty("dynamic_create", new StringValue("dynamic_create_clone_value_2"));
-      ValueMapAssert.assertEquals(expectedProps, props);
-   }
-
-   public void testInvokeReadOnly() throws Exception
-   {
-
-   }
-}

Modified: trunk/portlet/src/resources/tck-sar/META-INF/jboss-service.xml
===================================================================
--- trunk/portlet/src/resources/tck-sar/META-INF/jboss-service.xml	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/resources/tck-sar/META-INF/jboss-service.xml	2006-09-12 16:51:45 UTC (rev 5180)
@@ -147,7 +147,7 @@
 
    <!-- The producer portlet invoker -->
    <mbean
-      code="org.jboss.portal.portlet.state.producer.StatefulPortletInvoker"
+      code="org.jboss.portal.portlet.state.producer.ProducerPortletInvoker"
       name="portal:service=PortletInvoker,type=Producer"
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
@@ -202,7 +202,7 @@
 
    <!-- Preferences -->
    <mbean
-      code="org.jboss.portal.portlet.test.support.state.StateStoreSupport"
+      code="org.jboss.portal.portlet.impl.state.producer.ProducerPersistenceManagerService"
       name="portal:service=StateStore,type=Producer"
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">

Modified: trunk/portlet/src/resources/test-sar/META-INF/jboss-service.xml
===================================================================
--- trunk/portlet/src/resources/test-sar/META-INF/jboss-service.xml	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/portlet/src/resources/test-sar/META-INF/jboss-service.xml	2006-09-12 16:51:45 UTC (rev 5180)
@@ -154,13 +154,37 @@
 
    <!-- The producer portlet invoker -->
    <mbean
-      code="org.jboss.portal.portlet.state.producer.StatefulPortletInvoker"
+      code="org.jboss.portal.portlet.impl.state.producer.ProducerPersistenceManagerService"
+      name="portal:service=PersistenceManager,type=Producer"
+      xmbean-dd=""
+      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
+      <xmbean/>
+   </mbean>
+   <mbean
+      code="org.jboss.portal.portlet.impl.state.StateManagementPolicyService"
+      name="portal:service=StateManagementPolicy,type=Producer"
+      xmbean-dd=""
+      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
+      <xmbean/>
+      <attribute name="PersistLocally">true</attribute>
+   </mbean>
+   <mbean
+      code="org.jboss.portal.portlet.impl.state.StateConverterService"
+      name="portal:service=StateConverterService,type=Producer"
+      xmbean-dd=""
+      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
+      <xmbean/>
+   </mbean>
+   <mbean
+      code="org.jboss.portal.portlet.state.producer.ProducerPortletInvoker"
       name="portal:service=PortletInvoker,type=Producer"
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
       <xmbean/>
       <depends optional-attribute-name="PortletInvoker" proxy-type="attribute">portal:service=PortletInvoker,type=Container</depends>
-      <depends optional-attribute-name="StateStore" proxy-type="attribute">portal:service=StateStore,type=Producer</depends>
+      <depends optional-attribute-name="PersistenceManager" proxy-type="attribute">portal:service=PersistenceManager,type=Producer</depends>
+      <depends optional-attribute-name="StateManagementPolicy" proxy-type="attribute">portal:service=StateManagementPolicy,type=Producer</depends>
+      <depends optional-attribute-name="StateConverter" proxy-type="attribute">portal:service=StateConverterService,type=Producer</depends>
    </mbean>
 
    <!-- The container portlet invoker -->
@@ -207,15 +231,6 @@
       <depends optional-attribute-name="PortletSecurityService" proxy-type="attribute">portal:service=PortletSecurityService</depends>
    </mbean>
 
-   <!-- Preferences -->
-   <mbean
-      code="org.jboss.portal.portlet.test.support.state.StateStoreSupport"
-      name="portal:service=StateStore,type=Producer"
-      xmbean-dd=""
-      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
-      <xmbean/>
-   </mbean>
-
    <!-- Portal security services-->
    <mbean
       code="org.jboss.portal.security.impl.JBossAuthorizationDomainRegistryImpl"

Deleted: trunk/server/src/main/org/jboss/portal/server/impl/JBossInterceptorStackFactory.java
===================================================================
--- trunk/server/src/main/org/jboss/portal/server/impl/JBossInterceptorStackFactory.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/server/src/main/org/jboss/portal/server/impl/JBossInterceptorStackFactory.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -1,108 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.portal.server.impl.invocation;
-
-import org.jboss.portal.common.invocation.Interceptor;
-import org.jboss.portal.common.invocation.InterceptorStackFactory;
-import org.jboss.portal.common.invocation.InterceptorStack;
-import org.jboss.portal.jems.as.system.AbstractJBossService;
-
-import javax.management.ObjectName;
-import java.util.List;
-
-/**
- *
- * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
- * @version $Revision: 1.10 $
- */
-public class JBossInterceptorStackFactory extends AbstractJBossService implements InterceptorStackFactory
-{
-
-   /** . */
-   protected List interceptorNames;
-
-   protected InterceptorStack stack;
-
-   public List getInterceptorNames()
-   {
-      return interceptorNames;
-   }
-
-   public void setInterceptorNames(List interceptorNames)
-   {
-      this.interceptorNames = interceptorNames;
-   }
-
-   public InterceptorStack getInterceptorStack()
-   {
-      return stack;
-   }
-
-   /**
-    * Add's the supplied name to the list of interceptor names.
-    *
-    * @param name the intercptor's ObjectName.
-    * @throws Exception
-    */
-   public void addInterceptor(ObjectName name) throws Exception
-   {
-      interceptorNames.add(name);
-   }
-
-   /**
-    * Remove's the supplied name from the list of interceptor names.
-    *
-    * @param name the intercptor's ObjectName.
-    * @throws Exception
-    */
-   public void removeInterceptor(ObjectName name) throws Exception
-   {
-      interceptorNames.remove(name);
-   }
-
-   public void startService() throws Exception
-   {
-      rebuild();
-   }
-
-   /**
-    * Rebuild the interceptor stack.
-    */
-   public void rebuild() throws Exception
-   {
-      if (interceptorNames != null)
-      {
-         Interceptor[] interceptors = new Interceptor[interceptorNames.size()];
-         for (int i = 0; i < interceptorNames.size(); i++)
-         {
-            ObjectName name = (ObjectName)interceptorNames.get(i);
-            interceptors[i] = (Interceptor)server.getAttribute(name, "Interceptor");
-         }
-         stack = new JBossInterceptorStack(interceptors);
-      }
-   }
-
-   public void stopService()
-   {
-      this.stack = null;
-   }
-}

Added: trunk/server/src/main/org/jboss/portal/server/impl/MapAttributeResolver.java
===================================================================
--- trunk/server/src/main/org/jboss/portal/server/impl/MapAttributeResolver.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/server/src/main/org/jboss/portal/server/impl/MapAttributeResolver.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,78 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.server.impl;
+
+import org.jboss.portal.common.invocation.AttributeResolver;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class MapAttributeResolver implements AttributeResolver
+{
+
+   /** .
+    * */
+   private final Map attributes;
+
+   public MapAttributeResolver(Map attributes)
+   {
+      if (attributes == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      this.attributes = attributes;
+   }
+
+   public MapAttributeResolver()
+   {
+      this(new HashMap());
+   }
+
+   public Object getAttribute(String attrName) throws IllegalArgumentException
+   {
+      if (attrName == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      return attributes.get(attrName);
+   }
+
+   public void setAttribute(String attrName, Object attrValue) throws IllegalArgumentException
+   {
+      if (attrName == null)
+      {
+         throw new IllegalArgumentException();
+      }
+      if (attrValue != null)
+      {
+         attributes.put(attrName, attrValue);
+      }
+      else
+      {
+         attributes.remove(attrName);
+      }
+   }
+}

Copied: trunk/server/src/main/org/jboss/portal/server/impl/invocation/JBossInterceptorStackFactory.java (from rev 5179, trunk/server/src/main/org/jboss/portal/server/impl/JBossInterceptorStackFactory.java)
===================================================================
--- trunk/server/src/main/org/jboss/portal/server/impl/JBossInterceptorStackFactory.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/server/src/main/org/jboss/portal/server/impl/invocation/JBossInterceptorStackFactory.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -0,0 +1,108 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.portal.server.impl.invocation;
+
+import org.jboss.portal.common.invocation.Interceptor;
+import org.jboss.portal.common.invocation.InterceptorStackFactory;
+import org.jboss.portal.common.invocation.InterceptorStack;
+import org.jboss.portal.jems.as.system.AbstractJBossService;
+
+import javax.management.ObjectName;
+import java.util.List;
+
+/**
+ *
+ * @author <a href="mailto:julien at jboss.org">Julien Viet</a>
+ * @version $Revision: 1.10 $
+ */
+public class JBossInterceptorStackFactory extends AbstractJBossService implements InterceptorStackFactory
+{
+
+   /** . */
+   protected List interceptorNames;
+
+   protected InterceptorStack stack;
+
+   public List getInterceptorNames()
+   {
+      return interceptorNames;
+   }
+
+   public void setInterceptorNames(List interceptorNames)
+   {
+      this.interceptorNames = interceptorNames;
+   }
+
+   public InterceptorStack getInterceptorStack()
+   {
+      return stack;
+   }
+
+   /**
+    * Add's the supplied name to the list of interceptor names.
+    *
+    * @param name the intercptor's ObjectName.
+    * @throws Exception
+    */
+   public void addInterceptor(ObjectName name) throws Exception
+   {
+      interceptorNames.add(name);
+   }
+
+   /**
+    * Remove's the supplied name from the list of interceptor names.
+    *
+    * @param name the intercptor's ObjectName.
+    * @throws Exception
+    */
+   public void removeInterceptor(ObjectName name) throws Exception
+   {
+      interceptorNames.remove(name);
+   }
+
+   public void startService() throws Exception
+   {
+      rebuild();
+   }
+
+   /**
+    * Rebuild the interceptor stack.
+    */
+   public void rebuild() throws Exception
+   {
+      if (interceptorNames != null)
+      {
+         Interceptor[] interceptors = new Interceptor[interceptorNames.size()];
+         for (int i = 0; i < interceptorNames.size(); i++)
+         {
+            ObjectName name = (ObjectName)interceptorNames.get(i);
+            interceptors[i] = (Interceptor)server.getAttribute(name, "Interceptor");
+         }
+         stack = new JBossInterceptorStack(interceptors);
+      }
+   }
+
+   public void stopService()
+   {
+      this.stack = null;
+   }
+}

Modified: trunk/wsrp/src/main/org/jboss/portal/test/wsrp/v1/consumer/MarkupTestCase.java
===================================================================
--- trunk/wsrp/src/main/org/jboss/portal/test/wsrp/v1/consumer/MarkupTestCase.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/wsrp/src/main/org/jboss/portal/test/wsrp/v1/consumer/MarkupTestCase.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -29,6 +29,7 @@
 import org.jboss.portal.portlet.result.RenderResult;
 import org.jboss.portal.portlet.result.Result;
 import org.jboss.portal.portlet.spi.WindowContext;
+import org.jboss.portal.portlet.PortletContext;
 import org.jboss.portal.test.wsrp.TestWSRPProducerImpl;
 import org.jboss.portal.wsrp.consumer.ProducerSessionInformation;
 import org.jboss.portal.wsrp.core.CookieProtocol;
@@ -72,7 +73,7 @@
       action.setInstanceContext(new BasicInstanceContext(SOF.PORTLET_HANDLE_1));
       action.setSecurityContext(new BasicSecurityContext());
       action.setUserContext(new BasicUserContext());
-      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, SOF.PORTLET_HANDLE_1);
+      action.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, new PortletContext(SOF.PORTLET_HANDLE_1));
 
       consumer.invoke(action);
 
@@ -151,7 +152,7 @@
       TestPortletInvocationContext rc = new TestPortletInvocationContext();
 
       RenderInvocation render = new RenderInvocation(rc);
-      render.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, portletHandle);
+      render.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, new PortletContext(portletHandle));
 
       render.setInstanceContext(new BasicInstanceContext(portletHandle));
       render.setSecurityContext(new BasicSecurityContext());

Modified: trunk/wsrp/src/main/org/jboss/portal/wsrp/consumer/WSRPConsumerImpl.java
===================================================================
--- trunk/wsrp/src/main/org/jboss/portal/wsrp/consumer/WSRPConsumerImpl.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/wsrp/src/main/org/jboss/portal/wsrp/consumer/WSRPConsumerImpl.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -26,13 +26,14 @@
 import org.jboss.portal.portlet.NoSuchPortletException;
 import org.jboss.portal.portlet.Portlet;
 import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.PortletContext;
+import org.jboss.portal.portlet.state.PropertyMap;
 import org.jboss.portal.portlet.impl.spi.AbstractPortletInvocationContext;
 import org.jboss.portal.portlet.invocation.ActionInvocation;
 import org.jboss.portal.portlet.invocation.PortletInvocation;
 import org.jboss.portal.portlet.invocation.RenderInvocation;
 import org.jboss.portal.portlet.spi.UserContext;
 import org.jboss.portal.portlet.state.PropertyChange;
-import org.jboss.portal.portlet.state.PropertyMap;
 import org.jboss.portal.wsrp.UserContextConverter;
 import org.jboss.portal.wsrp.WSRPConstants;
 import org.jboss.portal.wsrp.WSRPConsumer;
@@ -193,7 +194,7 @@
       handler.handle(invocation);
    }
 
-   public String createClone(String portletId)
+   public PortletContext createClone(PortletContext portletContext) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
       throw new UnsupportedOperationException("createClone currently unsupported.");
    }
@@ -203,17 +204,17 @@
       throw new UnsupportedOperationException("destroyClone currently unsupported.");
    }
 
-   public PropertyMap getProperties(String portletId)
+   public PropertyMap getProperties(PortletContext portletContext, Set keys) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
       throw new UnsupportedOperationException("getProperties currently unsupported.");
    }
 
-   public PropertyMap getProperties(String portletId, Set keys)
+   public PropertyMap getProperties(PortletContext portletContext) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
       throw new UnsupportedOperationException("getProperties currently unsupported.");
    }
 
-   public void setProperties(String portletId, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
+   public PortletContext setProperties(PortletContext portletContext, PropertyChange[] changes) throws IllegalArgumentException, PortletInvokerException, UnsupportedOperationException
    {
       throw new UnsupportedOperationException("setProperties currently unsupported.");
    }
@@ -253,7 +254,7 @@
 
    static String getPortletHandle(PortletInvocation invocation)
    {
-      return (String)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE);
+      return ((PortletContext)invocation.getAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE)).getId();
    }
 
    WSRPPortletInfo getPortletInfo(PortletInvocation invocation)

Modified: trunk/wsrp/src/main/org/jboss/portal/wsrp/producer/MarkupHandler.java
===================================================================
--- trunk/wsrp/src/main/org/jboss/portal/wsrp/producer/MarkupHandler.java	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/wsrp/src/main/org/jboss/portal/wsrp/producer/MarkupHandler.java	2006-09-12 16:51:45 UTC (rev 5180)
@@ -191,7 +191,7 @@
          WSRPUtils.getJSR168WindowStateFromWSRPName(markupRequest.getWindowState()));
       RenderInvocation render = new RenderInvocation(renderContext);
       renderContext.contextualize(render);
-      render.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, portlet.getId());
+      render.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, new org.jboss.portal.portlet.PortletContext(portlet.getId()));
 
       try
       {
@@ -378,7 +378,7 @@
          markupRequest.getCharacterSet(), markupRequest.getMimeType());
       ActionInvocation invocation = new ActionInvocation(context);
       context.contextualize(invocation);
-      invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_ID_ATTRIBUTE, portlet.getId());
+      invocation.setAttribute(PortletInvocation.REQUEST_SCOPE, PortletInvocation.PORTLET_CONTEXT_ATTRIBUTE, new org.jboss.portal.portlet.PortletContext(portlet.getId()));
 
       try
       {

Modified: trunk/wsrp/src/resources/portal-wsrp-sar/META-INF/jboss-service.xml
===================================================================
--- trunk/wsrp/src/resources/portal-wsrp-sar/META-INF/jboss-service.xml	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/wsrp/src/resources/portal-wsrp-sar/META-INF/jboss-service.xml	2006-09-12 16:51:45 UTC (rev 5180)
@@ -23,15 +23,25 @@
       </depends-list>
    </mbean>
 
-   <!-- The state portlet invoker -->
+   <!-- The producer portlet invoker -->
    <mbean
-      code="org.jboss.portal.portlet.state.producer.StatefulPortletInvoker"
-      name="portal:service=WSRPPortletInvoker,type=Stateful"
+      code="org.jboss.portal.portlet.state.producer.ProducerPortletInvoker"
+      name="portal:service=PortletInvoker,type=WSRPProducer"
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
       <xmbean/>
-      <depends optional-attribute-name="StateStore" proxy-type="attribute">portal:service=StateStore,type=Producer</depends>
-      <depends optional-attribute-name="PortletInvoker" proxy-type="attribute">portal:service=WSRPPortletInvoker,type=Container</depends>
+      <depends
+         optional-attribute-name="PortletInvoker"
+         proxy-type="attribute">portal:service=WSRPPortletInvoker,type=Container</depends>
+      <depends
+         optional-attribute-name="PersistenceManager"
+         proxy-type="attribute">portal:service=PersistenceManager,type=Producer</depends>
+      <depends
+         optional-attribute-name="StateManagementPolicy"
+         proxy-type="attribute">portal:service=StateManagementPolicy,type=Producer</depends>
+      <depends
+         optional-attribute-name="StateConverter"
+         proxy-type="attribute">portal:service=StateConverter,type=Producer</depends>
    </mbean>
 
    <!-- The portlet container invoker -->
@@ -52,7 +62,7 @@
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
       <xmbean/>
-      <depends optional-attribute-name="Invoker" proxy-type="attribute">portal:service=WSRPPortletInvoker,type=Stateful</depends>
+      <depends optional-attribute-name="Invoker" proxy-type="attribute">portal:service=PortletInvoker,type=WSRPProducer</depends>
    </mbean>
 
    <!-- Configure a consumer that is the portal itself -->

Modified: trunk/wsrp/src/resources/test-wsrp-producer-sar/META-INF/jboss-service.xml
===================================================================
--- trunk/wsrp/src/resources/test-wsrp-producer-sar/META-INF/jboss-service.xml	2006-09-11 22:40:28 UTC (rev 5179)
+++ trunk/wsrp/src/resources/test-wsrp-producer-sar/META-INF/jboss-service.xml	2006-09-12 16:51:45 UTC (rev 5180)
@@ -17,9 +17,15 @@
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
       <xmbean/>
-      <depends optional-attribute-name="Deployer" proxy-type="attribute">portal:deployer=PortalWebApp</depends>
-      <depends optional-attribute-name="WebAppRegistry" proxy-type="attribute">portal:service=WebAppRegistry</depends>
-      <depends optional-attribute-name="Config" proxy-type="attribute">portal:service=ServerConfig</depends>
+      <depends
+         optional-attribute-name="Deployer"
+         proxy-type="attribute">portal:deployer=PortalWebApp</depends>
+      <depends
+         optional-attribute-name="WebAppRegistry"
+         proxy-type="attribute">portal:service=WebAppRegistry</depends>
+      <depends
+         optional-attribute-name="Config"
+         proxy-type="attribute">portal:service=ServerConfig</depends>
    </mbean>
 
    <!-- Portlet container stack -->
@@ -28,7 +34,7 @@
       name="portal:service=Interceptor,type=Portlet,name=ContextDispatcher"
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
-         <xmbean/>
+      <xmbean/>
    </mbean>
    <mbean
       code="org.jboss.portal.portlet.aspects.portlet.WindowStatesInterceptor"
@@ -65,37 +71,62 @@
       </depends-list>
    </mbean>
 
-   <!-- The state portlet invoker -->
+   <!-- The producer portlet invoker -->
    <mbean
-      code="org.jboss.portal.portlet.state.producer.StatefulPortletInvoker"
-      name="portal:service=PortletInvoker,type=Stateful"
+      code="org.jboss.portal.portlet.impl.state.producer.ProducerPersistenceManagerService"
+      name="portal:service=PersistenceManager,type=Producer"
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
       <xmbean/>
-      <depends optional-attribute-name="StateStore"
-               proxy-type="attribute">portal:service=StateStore,type=Producer</depends>
-      <depends optional-attribute-name="PortletInvoker" proxy-type="attribute">portal:service=PortletInvoker,type=Container</depends>
    </mbean>
-
-   <!-- The portlet container invoker -->
    <mbean
-      code="org.jboss.portal.portlet.container.PortletContainerInvoker"
-      name="portal:service=PortletInvoker,type=Container"
+      code="org.jboss.portal.portlet.impl.state.StateManagementPolicyService"
+      name="portal:service=StateManagementPolicy,type=Producer"
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
       <xmbean/>
-      <depends optional-attribute-name="StackFactory"
-               proxy-type="attribute">portal:service=InterceptorStackFactory,type=Container</depends>
-      <depends optional-attribute-name="Registry" proxy-type="attribute">portal:service=WebAppRegistry</depends>
+      <attribute name="PersistLocally">true</attribute>
    </mbean>
+   <mbean
+      code="org.jboss.portal.portlet.impl.state.StateConverterService"
+      name="portal:service=StateConverter,type=Producer"
+      xmbean-dd=""
+      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
+      <xmbean/>
+   </mbean>
+   <mbean
+      code="org.jboss.portal.portlet.state.producer.ProducerPortletInvoker"
+      name="portal:service=PortletInvoker,type=Stateful"
+      xmbean-dd=""
+      xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
+      <xmbean/>
+      <depends
+         optional-attribute-name="PortletInvoker"
+         proxy-type="attribute">portal:service=PortletInvoker,type=Container</depends>
+      <depends
+         optional-attribute-name="PersistenceManager"
+         proxy-type="attribute">portal:service=PersistenceManager,type=Producer</depends>
+      <depends
+         optional-attribute-name="StateManagementPolicy"
+         proxy-type="attribute">portal:service=StateManagementPolicy,type=Producer</depends>
+      <depends
+         optional-attribute-name="StateConverter"
+         proxy-type="attribute">portal:service=StateConverter,type=Producer</depends>
+   </mbean>
 
-   <!-- Preferences -->
+   <!-- The portlet container invoker -->
    <mbean
-      code="org.jboss.portal.portlet.test.support.state.StateStoreSupport"
-      name="portal:service=StateStore,type=Producer"
+      code="org.jboss.portal.portlet.container.PortletContainerInvoker"
+      name="portal:service=PortletInvoker,type=Container"
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
       <xmbean/>
+      <depends
+         optional-attribute-name="StackFactory"
+         proxy-type="attribute">portal:service=InterceptorStackFactory,type=Container</depends>
+      <depends
+         optional-attribute-name="Registry"
+         proxy-type="attribute">portal:service=WebAppRegistry</depends>
    </mbean>
 
    <!-- WSRP Producer implementation -->
@@ -105,8 +136,9 @@
       xmbean-dd=""
       xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
       <xmbean/>
-      <depends optional-attribute-name="Invoker"
-               proxy-type="attribute">portal:service=PortletInvoker,type=Stateful</depends>
+      <depends
+         optional-attribute-name="Invoker"
+         proxy-type="attribute">portal:service=PortletInvoker,type=Stateful</depends>
       <attribute name="RemotableByDefault">true</attribute>
    </mbean>
 




More information about the jboss-svn-commits mailing list