@Override
public String encodeActionURL(String url)
{
String viewId = null, path = null;
boolean nonFacesAction = false;
QueryString queryStr = null;
int queryStart = -1;
boolean isPortletURL = false;
Bridge.PortletPhase urlType = getPortletPhase();
// First check to see if the special URI indicating we should encode
// a Nonfaces target to just the current portlet (without an associated
// path based resource).
if (isPortletURL(url))
{
isPortletURL = true;
nonFacesAction = true;
//URL is of the form scheme:urlType?queryString
// remove the scheme
path = url.substring(url.indexOf(":")+ 1);
queryStart = url.indexOf('?');
if (queryStart != -1)
{
// Get the query string
queryStr = new QueryString(path.substring(queryStart + 1), "UTF8");
path = path.substring(0, queryStart);
}
if (path.equalsIgnoreCase("render"))
{
urlType = Bridge.PortletPhase.RENDER_PHASE;
}
else if (path.equalsIgnoreCase("action"))
{
urlType = Bridge.PortletPhase.ACTION_PHASE;
}
else if (path.equalsIgnoreCase("resource"))
{
urlType = Bridge.PortletPhase.RESOURCE_PHASE;
}
else
{
log("PortletExternalContextImpl.encodeActionURL: malformed portlet url "
+ url);
return url;
}
}
else if (url.startsWith("#") || isExternalURL(url) || isDirectLink(url))
{
return url;
}
else
{
// Its a Path encoded URL
// url might contain DirectLink=false parameter -- spec says remove if
// it does.
url = removeDirectLink(url);
// Now determine the target viewId
// First: split URL into path and query string
// Hold onto QueryString for later processing
queryStart = url.indexOf('?');
if (queryStart != -1)
{
// Get the query string
queryStr = new QueryString(url.substring(queryStart + 1), "UTF8");
path = url.substring(0, queryStart);
}
else
{
path = url;
// construct an empty queryString to hold the viewId
queryStr = new QueryString("UTF8");
}
// Convert relative path to context path
if (isRelativePath(path))
{
path = getPathFromRelativePath(path);
}
// Now se if this is a Faces URL
viewId = getViewIdFromPath(path);
if (viewId != null)
{
encodeFacesActionTarget(queryStr, viewId);
}
else
{
// URL points at non-Faces action
nonFacesAction = true;
encodeNonFacesActionTarget(queryStr, path);
}
}
if (getPortletPhase() == Bridge.PortletPhase.RENDER_PHASE ||
getPortletPhase() == Bridge.PortletPhase.RESOURCE_PHASE)
{ // render - write
// the viewId into
// the response
// (interaction
// state)
MimeResponse mimeResponse = (MimeResponse) getResponse();
PortletURL actionURL = null;
ResourceURL resourceURL = null;
BaseURL baseURL = null;
// Non-JSF actions are renderURLs as we merely dispatch to them
if (nonFacesAction)
{
if (isPortletURL && urlType == Bridge.PortletPhase.ACTION_PHASE)
{
baseURL = actionURL = mimeResponse.createActionURL();
}
else if (isPortletURL && urlType == Bridge.PortletPhase.RESOURCE_PHASE)
{
baseURL = resourceURL = mimeResponse.createResourceURL();
}
else
{
baseURL = actionURL = mimeResponse.createRenderURL();
}
}
else
{
baseURL = actionURL = mimeResponse.createActionURL();
}
// Add parameters so they don't get lost
Enumeration<String> list = queryStr.getParameterNames();
while (list.hasMoreElements())
{
String param = list.nextElement().toString();
if (actionURL != null && param.equals(Bridge.PORTLET_MODE_PARAMETER))
{
try
{
actionURL.setPortletMode(new PortletMode(queryStr.getParameter(param)));
}
catch (Exception e)
{
; // do nothing -- just ignore
}
}
else if (actionURL != null && param.equals(Bridge.PORTLET_WINDOWSTATE_PARAMETER))
{
try
{
actionURL.setWindowState(new WindowState(queryStr.getParameter(param)));
}
catch (Exception e)
{
; // do nothing -- just ignore
}
}
else if (param.equals(Bridge.PORTLET_SECURE_PARAMETER))
{
try
{
baseURL.setSecure(Boolean.getBoolean(queryStr.getParameter(param)));
}
catch (Exception e)
{
; // do nothing -- just ignore
}
}
else
{
baseURL.setParameter(param, queryStr.getParameter(param));
}
}
// Some portlet containers implementing wsrp choose to separate the
// consumer rewrite string that represents this URL using & as the
// spec allows for either that or &. If the container has chosen to
// to do such -- undo it (use & instead) as faces renderkits/response writers
// may reencode when writing XMl content.
url = baseURL.toString();
url = url.replaceAll("\\&\\;", "&");
}
else if (getPortletPhase() == Bridge.PortletPhase.ACTION_PHASE ||
getPortletPhase() == Bridge.PortletPhase.EVENT_PHASE)
{ // action - write the viewId to navigational state
StateAwareResponse stateResponse = (StateAwareResponse) getResponse();
// set request params into navigational states
Enumeration<String> list = queryStr.getParameterNames();
while (list.hasMoreElements())
{
String param = list.nextElement();
if (param.equals(Bridge.PORTLET_MODE_PARAMETER))
{
try
{
stateResponse.setPortletMode(new PortletMode(queryStr.getParameter(param)));
}
catch (Exception e)
{
//TODO: Ignoring is probably dangerous here as it means that we are
// EITHER using exceptions for flow control (which is extreemly
// inefficient) or we should log a message saying what the issue
// is. According to the Javadocs an exception is thrown here if the
// portlet mode is not allowed or if sendRedirect has already been
// called. In either case we should log an information type message
// here.
; // do nothing -- just ignore
}
}
else if (param.equals(Bridge.PORTLET_WINDOWSTATE_PARAMETER))
{
try
{
stateResponse.setWindowState(new WindowState(queryStr.getParameter(param)));
}
catch (Exception e)
{
; // do nothing -- just ignore
}
}
else if (param.equals(Bridge.PORTLET_SECURE_PARAMETER))
{
; // ignore -- do nothing as can't encode into an actionResponse
}
else
{
stateResponse.setRenderParameter(param, queryStr.getParameter(param));
}
}
}
// Because we want to support translating a redirect that occurs
// during a render as an in place navigation AND we can't reverse