}
public PortletInvocationResponse invoke(PortletInvocation invocation) throws PortletInvokerException, InvocationException
{
// Get the context of the portlet that the client want to use
final PortletContext portletContext = invocation.getTarget();
if (portletContext == null)
{
throw new InvocationException("No portlet context provided");
}
// Get the access mode
InstanceContext instanceCtx = invocation.getInstanceContext();
AccessMode access = instanceCtx.getAccessMode();
// Get a state contxt for the portlet context
InternalContext context = getStateContext(portletContext);
// If it is a producer offered portlet we consider read-write as read-only
if (!context.isStateful() && access == AccessMode.READ_WRITE)
{
access = AccessMode.READ_ONLY;
}
// Get the portlet container and set it on invocation
Portlet portlet = super.getPortlet(context.getPortletContext());
if (portlet == null)
{
throw new NoSuchPortletException("Portlet " + context.getPortletContext() + " not found", context.getPortletId());
}
// Create prefs
AbstractPropertyContext prefs = new AbstractPropertyContext(
access,
context.isStateful() ? ((StatefulContext)context).getProperties() : null,
invocation instanceof RenderInvocation);
//
PortletInvocationResponse response;
try
{
invocation.setTarget(context.getPortletContext());
invocation.setAttribute(PropertyContext.PREFERENCES_ATTRIBUTE, prefs);
// Invoke
response = super.invoke(invocation);
}
finally
{
invocation.setTarget(portletContext);
invocation.removeAttribute(PropertyContext.PREFERENCES_ATTRIBUTE);
}
//
int status = prefs.getStatus();
// Producer state management if the invocation was succesful
if ((invocation instanceof ActionInvocation || invocation instanceof ResourceInvocation || invocation instanceof EventInvocation) && status == AbstractPropertyContext.UPDATE_SUCCESSFUL)
{
// Get the potentially updated prefs
PropertyMap newPrefs = prefs.getPrefs();
//
PortletStateType stateType = instanceCtx.getStateType();
boolean persistLocally;
if (stateType == null)
{
persistLocally = true;
}
else
{
persistLocally = stateManagementPolicy.persistLocally();
}
//
switch(access)
{
case CLONE_BEFORE_WRITE:
{
// Create the state
if (context.isStateful())
{
StatefulContext statefulContext = (StatefulContext)context;
if (persistLocally)
{
try
{
// The state id should be ok as it was used before to load the state
LocalContext localContext = (LocalContext)statefulContext;
String portletStateId = localContext.getStateId();
String cloneStateId = persistenceManager.cloneState(portletStateId, newPrefs);
// Return the clone context
String cloneId = PRODUCER_CLONE_ID_PREFIX + cloneStateId;
PortletContext clonedCtx = PortletContext.createPortletContext(cloneId);
StateEvent event = new StateEvent(clonedCtx, StateEvent.Type.PORTLET_CLONED_EVENT);
instanceCtx.onStateEvent(event);
}
catch (NoSuchStateException e)
{
throw new PortletInvokerException("Unexpected exception", e);
}
catch (InvalidStateIdException e)
{
throw new PortletInvokerException("Unexpected exception", e);
}
}
else
{
PortletContext clonedCtx = marshall(stateType, context.getPortletId(), newPrefs);
StateEvent event = new StateEvent(clonedCtx, StateEvent.Type.PORTLET_CLONED_EVENT);
instanceCtx.onStateEvent(event);
}
}
else
{
// Add the missing mutable portlet state
getPropertiesFromMetaData(portlet.getContext(), newPrefs);
//
if (persistLocally)
{
// Create the new state
String cloneStateId = persistenceManager.createState(context.getPortletId(), newPrefs);
// Return the clone context
String cloneId = PRODUCER_CLONE_ID_PREFIX + cloneStateId;
PortletContext clonedCtx = PortletContext.createPortletContext(cloneId);
StateEvent event = new StateEvent(clonedCtx, StateEvent.Type.PORTLET_CLONED_EVENT);
instanceCtx.onStateEvent(event);
}
else
{
PortletContext clonedCtx = marshall(stateType, context.getPortletId(), newPrefs);
StateEvent event = new StateEvent(clonedCtx, StateEvent.Type.PORTLET_CLONED_EVENT);
instanceCtx.onStateEvent(event);
}
}
break;
}
case READ_WRITE:
{
StatefulContext statefulContext = (StatefulContext)context;
if (statefulContext.isLocal())
{
// Update the state
try
{
LocalContext localContext = (LocalContext)statefulContext;
String stateId = localContext.getStateId();
persistenceManager.updateState(stateId, newPrefs);
}
catch (NoSuchStateException e)
{
throw new PortletInvokerException("Unexpected exception", e);
}
catch (InvalidStateIdException e)
{
throw new PortletInvokerException("Unexpected exception", e);
}
}
else
{
PortletContext modifiedCtx = marshall(stateType, context.getPortletId(), newPrefs);
StateEvent event = new StateEvent(modifiedCtx, StateEvent.Type.PORTLET_MODIFIED_EVENT);
instanceCtx.onStateEvent(event);
}
break;
}