You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mf...@apache.org on 2011/02/08 19:17:39 UTC
svn commit: r1068501 - in /myfaces/portlet-bridge/core/trunk_3.0.x:
api/src/main/java/javax/portlet/faces/
impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/
impl/src/main/java/org/apache/myfaces/portlet/faces/context/
impl/src/main/java/org/a...
Author: mfreedman
Date: Tue Feb 8 18:17:38 2011
New Revision: 1068501
URL: http://svn.apache.org/viewvc?rev=1068501&view=rev
Log:
PORTLETBRIDGE-182: renderURLs shouldn't carry forward scope by default
PORTLETBRIDGE-181: Need to add impls for ExternalContext methods not currently implemented
PORTLETBRIDGE-180: Update extension to view mapping to account for JSF 2.0 support of a list of mappable extensions
PORTLETBRIDGE-179: Mojarra 2.0 contains some FacesContext attributed that expect to be held for a full lifecycle
PORTLETBRIDGE-178: Support Views using Ajax that reference component ids (in the execute or render id list)
PORTLETBRIDGE-177: Support Bookmarkable URLs
PORTLETBRIDGE-176: Handle Urls with # (fragments) in them
PORTLETBRIDGE-175: Bridge phase listeners have portlet dependecy but can be executed in a servlet request yielding ClassCastException
PORTLETBRIDGE-174: Portlet Bridge 3.0.0 -- PortletViewHandler.render needs to reference MimeResponse after the check for portlet request
Added:
myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletPartialViewContextFactoryImpl.java
myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletPartialViewContextImpl.java
Modified:
myfaces/portlet-bridge/core/trunk_3.0.x/api/src/main/java/javax/portlet/faces/Bridge.java
myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java
myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/URLUtils.java
myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/resources/META-INF/faces-config.xml
Modified: myfaces/portlet-bridge/core/trunk_3.0.x/api/src/main/java/javax/portlet/faces/Bridge.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_3.0.x/api/src/main/java/javax/portlet/faces/Bridge.java?rev=1068501&r1=1068500&r2=1068501&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_3.0.x/api/src/main/java/javax/portlet/faces/Bridge.java (original)
+++ myfaces/portlet-bridge/core/trunk_3.0.x/api/src/main/java/javax/portlet/faces/Bridge.java Tue Feb 8 18:17:38 2011
@@ -362,7 +362,15 @@ Bridge
* to reestablish the state.
*/
public static final String FACES_USE_CURRENT_VIEW_PARAMETER = "_jsfBridgeCurrentView";
-
+
+
+ /** Special parameter name recognized during <code>encodeActionURL</code>. When an url
+ * passed to <code>encodeActionURL</code> contains a parameter with this name and a value of true,
+ * and its during the render phase of the Faces lifecycle, it removes the parameter
+ * before encoding the url as a render url. I.e. you end up with a Portlet render url
+ * rather than a portlet action url.
+ */
+ public static final String BOOKMARKABLE_URL = "_jsfBridgeBookmarkableUrl";
/** Enumeration whose values describe the current portlet phase the bridge
* is executing Faces within.
Modified: myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java?rev=1068501&r1=1068500&r2=1068501&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java Tue Feb 8 18:17:38 2011
@@ -142,6 +142,7 @@ public class BridgeImpl
public static final String PORTLET_NAME_ATTRIBUTE = "org.apache.myfaces.portlet.faces.portletName";
public static final String VIEWID_QUERYSTRING_ATTRIBUTE = "org.apache.myfaces.portlet.faces.viewIdQueryString";
+ private static final String FACES_CONTEXT_SCOPE = "org.apache.myfaces.portlet.faces.includeInScope.facesContextScope";
private static final String REQUEST_SCOPE_LOCK = "org.apache.myfaces.portlet.faces.requestScopeLock";
private static final String REQUEST_SCOPE_MAP = "org.apache.myfaces.portlet.faces.requestScopeMap";
private static final String SCOPE_VIEW_KEY = "org.apache.myfaces.portlet.faces.includeInScope.scopeViewKey";
@@ -167,6 +168,7 @@ public class BridgeImpl
private BridgeEventHandler mEventHandler = null;
private BridgePublicRenderParameterHandler mProcessPRPHandler = null;
private List<String> mFacesMappings = null;
+ private List<String> mPreservedFacesContextScopeAttrs = null;
private boolean mInitialized = false;
private Boolean mDebugLoggingEnabled;
@@ -220,6 +222,19 @@ public class BridgeImpl
// acquire any config information in faces-config.xml
processFacesConfiguration(portletContext);
+
+
+ // Hack get the names of attrs to preserve from the FacesContext scope until render ends
+ String preserve = mPortletConfig.getInitParameter("org.apache.myfaces.portlet.faces.preserveFacesContextScopedAttrs");
+ if (preserve != null)
+ {
+ String[] attrs = preserve.split(",");
+ for (int i = 0; i < attrs.length; i++)
+ {
+ attrs[i] = attrs[i].trim();
+ }
+ mPreservedFacesContextScopeAttrs = Arrays.asList(attrs);
+ }
// Set up the synchronziation object for the RequestScopeMap as we don't
// want to sync on the PortletContext because its too broad. Note:
@@ -851,8 +866,8 @@ public class BridgeImpl
}
- // never restore a scope if relying on render redirect cache
- if (redirectParams == null && !clientDirectedView)
+ // never restore a scope if relying on render redirect cache or its a renderURL
+ if (redirectParams == null && !clientDirectedView && request.getParameter(PortletExternalContextImpl.RENDERURL_NO_SCOPE) == null)
{
// If available -- restore the bridge request scope before getting the
// FacesContext in case anything in the context construction relies
@@ -1643,25 +1658,78 @@ public class BridgeImpl
saveFacesMessageState(context);
// now place the viewRoot in the request scope
+ UIViewRoot vr = context.getViewRoot();
Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
- requestMap.put(FACES_VIEWROOT, context.getViewRoot());
+ requestMap.put(FACES_VIEWROOT, vr);
+
+ // Preserve the FC scope so its not lost when restart this lifecycle in the render
+ HashMap<Object, Object> preserved = mPreservedFacesContextScopeAttrs(context);
+ if (preserved != null)
+ {
+ requestMap.put(FACES_CONTEXT_SCOPE, preserved);
+ }
+ }
+
+ private HashMap<Object, Object> mPreservedFacesContextScopeAttrs(FacesContext context)
+ {
+ if (mPreservedFacesContextScopeAttrs == null || mPreservedFacesContextScopeAttrs.isEmpty())
+ {
+ return null;
+ }
+
+ Map<Object, Object> attrs = context.getAttributes();
+ if (attrs == null || attrs.isEmpty())
+ {
+ return null;
+ }
+
+ HashMap<Object, Object> m = new HashMap(5);
+
+ for (String key : mPreservedFacesContextScopeAttrs)
+ {
+ if (attrs.containsKey(key))
+ {
+ m.put(key, attrs.get(key));
+ }
+ else if (key.equalsIgnoreCase("org.apache.myfaces.portlet.faces.viewRoot"))
+ {
+ if (attrs.containsKey(context.getViewRoot()))
+ {
+ m.put(context.getViewRoot(), attrs.get(context.getViewRoot()));
+ }
+ }
+ }
+ return m;
}
private boolean restoreFacesView(FacesContext context, String scopeId)
{
Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
- UIViewRoot viewRoot = (UIViewRoot) requestMap.get(FACES_VIEWROOT);
+ UIViewRoot viewRoot = (UIViewRoot) requestMap.remove(FACES_VIEWROOT);
if (viewRoot != null)
{
context.setViewRoot(viewRoot);
- // remove from current Request Scope
- requestMap.remove(FACES_VIEWROOT);
-
- // Delay removing from the bridge request scope until after we are sure that
- // render completes okay and the state is saved by Faces -- otherwise
- // we won't be able to reply/retry,
}
+
+ // restore FC scope without overwriting existing/new values
+ Map<Object, Object> attrs = (Map<Object, Object>) requestMap.remove(FACES_CONTEXT_SCOPE);
+ if (attrs != null)
+ {
+ Map<Object, Object> ctxAttrs = context.getAttributes();
+ for (Map.Entry<Object, Object> entry : attrs.entrySet())
+ {
+ if (!ctxAttrs.containsKey(entry.getKey()))
+ {
+ ctxAttrs.put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ // Delay removing from the bridge request scope until after we are sure that
+ // render completes okay and the state is saved by Faces -- otherwise
+ // we won't be able to reply/retry,
+
// Messages get restored in a phase listener
return viewRoot != null;
@@ -1763,9 +1831,14 @@ public class BridgeImpl
}
// If this is the first render after an action the cached view will also
- // be in the scope. Remove it so its not used again.
+ // be in the scope (as well as its FC scope. Remove it so its not used again.
// get the managedScopeMap
scopeMap.remove(FACES_VIEWROOT);
+ Map<Object, Object> attrs = (Map<Object, Object>) scopeMap.remove(FACES_CONTEXT_SCOPE);
+ if (attrs != null)
+ {
+ attrs.clear();
+ }
}
}
@@ -2610,7 +2683,7 @@ public class BridgeImpl
// There is only one lifecycle instance within a webapp -- and lifecycles aren't thread safe
// This means we may have multiple listeners registered and/or multiple simulataneous requests
// So only do the work if the FacesContext of the event is equal to the one in the current thread
- if (context != FacesContext.getCurrentInstance())
+ if (context != FacesContext.getCurrentInstance() || !BridgeUtil.isPortletRequest())
{
return;
}
@@ -2654,7 +2727,7 @@ public class BridgeImpl
// There is only one lifecycle instance within a webapp -- and lifecycles aren't thread safe
// This means we may have multiple listeners registered and/or multiple simulataneous requests
// So only do the work if the FacesContext of the event is equal to the one in the current thread
- if (context != FacesContext.getCurrentInstance())
+ if (context != FacesContext.getCurrentInstance() || !BridgeUtil.isPortletRequest())
{
return;
}
Modified: myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java?rev=1068501&r1=1068500&r2=1068501&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java Tue Feb 8 18:17:38 2011
@@ -30,11 +30,13 @@ import java.net.URL;
import java.net.URLEncoder;
import java.security.Principal;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -57,6 +59,7 @@ import javax.portlet.PortletRequestDispa
import javax.portlet.PortletResponse;
import javax.portlet.PortletSession;
import javax.portlet.PortletURL;
+import javax.portlet.ResourceResponse;
import javax.portlet.ResourceURL;
import javax.portlet.StateAwareResponse;
import javax.portlet.WindowState;
@@ -92,6 +95,9 @@ public class PortletExternalContextImpl
public static final String FACES_MAPPING_ATTRIBUTE =
"org.apache.myfaces.portlet.faces.context.facesMapping";
+ private static final String FACES_SUFFIXES =
+ "org.apache.myfaces.portlet.faces.context.facesSuffixes";
+
// Note: be careful -- as this attribute is prefixed to a value containing '.' it
// wouldn't be exlcuded using normal logic -- so instead BridgeImpl specially
// exlcudes/treats this package. -- i.e. all attrbiutes beginning with
@@ -105,6 +111,7 @@ public class PortletExternalContextImpl
// Render parameter to store the viewId
public static final String JSF_TARGET_VIEWID_RENDER_PARAMETER = "__jpfbJSFTARGET";
+ public static final String RENDERURL_NO_SCOPE = "__jpfbUSESCOPE";
public static final String NO_SCOPE = "org.apache.myfaces.portlet.faces.noScope";
public static final String SERVLET_INCLUDED_PATHINFO_ATTRIBUTE = "javax.servlet.include.path_info";
@@ -150,6 +157,7 @@ public class PortletExternalContextImpl
// Reverse engineered serlvet paths from mappings
private List<String> mFacesMappings = null;
+ private List<String> mFacesSuffixes = null;
private String mServletPath = null;
private String mPathInfo = null;
private String mIncludedServletPath = null;
@@ -178,6 +186,11 @@ public class PortletExternalContextImpl
"." + Bridge.DEFAULT_RENDERKIT_ID);
mFacesMappings = (List<String>) mPortletRequest.getAttribute(FACES_MAPPING_ATTRIBUTE);
+ mFacesSuffixes = (List<String>) mPortletContext.getAttribute(FACES_SUFFIXES);
+ if (mFacesSuffixes == null)
+ {
+ mFacesSuffixes = parseFacesSuffixes();
+ }
setFacesVersionDependencyFlags();
@@ -348,6 +361,7 @@ public class PortletExternalContextImpl
int queryStart = -1;
boolean isPortletURLSelfReference = false;
boolean isStrictXhtmlEncoded = isStrictXhtmlEncoded(url);
+ boolean encodeScopeInRenderUrl = false;
Bridge.PortletPhase urlType = Bridge.PortletPhase.ACTION_PHASE;
// First check to see if the special URI indicating we should encode
@@ -475,6 +489,22 @@ public class PortletExternalContextImpl
MimeResponse mimeResponse = (MimeResponse) getResponse();
PortletURL actionURL = null;
BaseURL baseURL = null;
+
+ // first test if the url has been explicitly marked as bookmarkable
+ String bookmarkableURL = queryStr.getParameter(Bridge.BOOKMARKABLE_URL);
+ if (bookmarkableURL != null)
+ {
+ urlType = Bridge.PortletPhase.RENDER_PHASE;
+ if ("false".equalsIgnoreCase(bookmarkableURL))
+ {
+ // special case -- allows someone encoding a render url to indicate that this is
+ // a refresh/redisplay link and hence should retain the scope (used by the TCK)
+ encodeScopeInRenderUrl = true;
+ }
+ }
+ // Always remove - even if not there/not true
+ queryStr.removeParameter(Bridge.BOOKMARKABLE_URL);
+
// Non-JSF actions are renderURLs as we merely dispatch to them
if (urlType == Bridge.PortletPhase.ACTION_PHASE)
{
@@ -487,6 +517,10 @@ public class PortletExternalContextImpl
else
{
baseURL = actionURL = mimeResponse.createRenderURL();
+ if (!encodeScopeInRenderUrl)
+ {
+ actionURL.setParameter(RENDERURL_NO_SCOPE, "1");
+ }
}
// Add parameters so they don't get lost
@@ -615,6 +649,8 @@ public class PortletExternalContextImpl
return url;
}
+
+
private void carryForwardRenderParameters(BaseURL url, Map<String, String[]> m, QueryString queryStr, Map<String, String[]> addedActionParams)
{
Set<Map.Entry<String, String[]>> s = m.entrySet();
@@ -629,6 +665,31 @@ public class PortletExternalContextImpl
}
}
}
+
+ @Override
+ public String encodeBookmarkableURL(String baseUrl, Map<String,List<String>> parameters)
+ {
+ // Faces calls encodeActionURL after this method -- hence expected result is
+ // a valif URL string. So need to mark this url so encodeActionUrl knows to
+ // encode as a renderUrl. However don't overwrite/add if the url already contains
+ // the special QS parameter as this QS param with a value of false means
+ // the scope should be added -- as one sees the default is a renderUrl without
+ // scope -- so if its already exists in the QS its likely a redisplay url
+ if (!baseUrl.contains(Bridge.BOOKMARKABLE_URL))
+ {
+ HashMap<String,List<String>> params = new HashMap<String,List<String>>(parameters);
+
+ // add a new parameter that signifies its a render/bookmarkable url
+ ArrayList<String> val = new ArrayList(1);
+ val.add(0, "true");
+ params.put(Bridge.BOOKMARKABLE_URL, val);
+ return URLUtils.appendURLArguments(baseUrl, params);
+ }
+ else
+ {
+ return URLUtils.appendURLArguments(baseUrl, parameters);
+ }
+ }
@Override
public Flash getFlash()
@@ -1063,6 +1124,7 @@ public class PortletExternalContextImpl
{
return mPortletRequest.getPortletSession(create);
}
+
@Override
public Object getContext()
@@ -1509,7 +1571,29 @@ public class PortletExternalContextImpl
//}
}
-
+
+ @Override
+ public void setResponseBufferSize(int size)
+ {
+ if (mPortletResponse instanceof MimeResponse)
+ {
+ ((MimeResponse)mPortletResponse).setBufferSize(size);
+ }
+
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public void setResponseContentLength(int length)
+ {
+ if (mPortletResponse instanceof ResourceResponse)
+ {
+ ((ResourceResponse)mPortletResponse).setContentLength(length);
+ }
+
+ // Otherwise Do nothing;
+ }
+
/**
*
* <p>
@@ -1699,6 +1783,36 @@ public class PortletExternalContextImpl
throw new IllegalStateException();
}
+
+ @Override
+ public int getResponseBufferSize()
+ {
+ if (mPortletResponse instanceof MimeResponse)
+ {
+ return ((MimeResponse)mPortletResponse).getBufferSize();
+ }
+
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public void responseFlushBuffer() throws IOException
+ {
+ if (mPortletResponse instanceof MimeResponse)
+ {
+ ((MimeResponse)mPortletResponse).flushBuffer();
+ }
+
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public void responseSendError(int statusCode,
+ String message) throws IOException
+ {
+
+ throw new IOException(new StringBuffer(message.length()+4).append(statusCode).append(": ").append(message).toString());
+ }
/**
* <p>
@@ -2265,7 +2379,7 @@ public class PortletExternalContextImpl
if (isSuffixedMapped(url, mFacesMappings))
{
viewId =
- viewIdFromSuffixMapping(url, mFacesMappings, mPortletContext.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME));
+ viewIdFromSuffixMapping(url, mFacesSuffixes);
}
else if (isPrefixedMapped(url, mFacesMappings))
{
@@ -2278,6 +2392,17 @@ public class PortletExternalContextImpl
}
return viewId;
}
+
+ private List<String> parseFacesSuffixes()
+ {
+ String suffixString = mPortletContext.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
+ if (suffixString == null)
+ {
+ suffixString = ViewHandler.DEFAULT_SUFFIX;
+ }
+
+ return Arrays.asList(suffixString.split(" "));
+ }
private boolean isSuffixedMapped(String url, List<String> mappings)
{
@@ -2287,25 +2412,34 @@ public class PortletExternalContextImpl
return ext != null && mappings.contains(ext);
}
- private String viewIdFromSuffixMapping(String url, List<String> mappings, String ctxDefault)
+ private String viewIdFromSuffixMapping(String url, List<String> suffixes)
{
- // replace extension with the DEFAULT_SUFFIX
- if (ctxDefault == null)
- {
- ctxDefault = ViewHandler.DEFAULT_SUFFIX;
- }
-
int i = url.lastIndexOf(".");
- if (ctxDefault != null && i != -1)
+ if (i != -1)
{
- if (ctxDefault.startsWith("."))
- {
- url = url.substring(0, i) + ctxDefault;
- }
- else
+ for (String suffix : suffixes)
{
- // shouldn't happen
- url = url.substring(0, i) + "." + ctxDefault;
+ if (suffix.startsWith("."))
+ {
+ url = url.substring(0, i) + suffix;
+ }
+ else
+ {
+ // shouldn't happen
+ url = url.substring(0, i) + "." + suffix;
+ }
+ // now verify if this exists
+ String testPath = url.startsWith("/") ? url : "/"+url;
+ try
+ {
+ if (mPortletContext.getResource(testPath) != null)
+ {
+ break;
+ }
+ } catch (MalformedURLException m)
+ {
+ // TODO: didn't expect to get here
+ }
}
}
return url;
Added: myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletPartialViewContextFactoryImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletPartialViewContextFactoryImpl.java?rev=1068501&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletPartialViewContextFactoryImpl.java (added)
+++ myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletPartialViewContextFactoryImpl.java Tue Feb 8 18:17:38 2011
@@ -0,0 +1,66 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.myfaces.portlet.faces.context;
+
+import javax.faces.context.PartialViewContextFactory;
+import javax.faces.context.PartialViewContext;
+import javax.faces.context.FacesContext;
+import javax.faces.context.FacesContextFactory;
+
+/**
+ * <p>
+ * Factory to vend extension to the default <code>PartialViewContext</code> instance.
+ * Its exists so the bridge can modify execute/render ids to be true clientIds:\
+ * issue caused because developers may provide a specific id in html and then reference
+ * in there javascript -- because the bridge adds a namespace these aren't the true ids
+ * however because they are explictly named by developer they are what is passed. The
+ * bridge needs to convert these "ids" to "clientids"
+ * </p>
+ */
+public class PortletPartialViewContextFactoryImpl extends PartialViewContextFactory
+{
+
+ private PartialViewContextFactory mFactory;
+
+ public PortletPartialViewContextFactoryImpl(PartialViewContextFactory factory)
+ {
+ mFactory = factory;
+ }
+
+ @Override
+ public PartialViewContextFactory getWrapped()
+ {
+ return mFactory;
+ }
+
+
+ // ---------------------------------- Methods from PartialViewContextFactory
+
+
+ /**
+ * @see PartialViewContextFactory#getPartialViewContext(javax.faces.context.FacesContext)
+ */
+ public PartialViewContext getPartialViewContext(FacesContext context) {
+
+ return new PortletPartialViewContextImpl(getWrapped().getPartialViewContext(context));
+
+ }
+
+}
Added: myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletPartialViewContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletPartialViewContextImpl.java?rev=1068501&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletPartialViewContextImpl.java (added)
+++ myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletPartialViewContextImpl.java Tue Feb 8 18:17:38 2011
@@ -0,0 +1,208 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.myfaces.portlet.faces.context;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.faces.component.ContextCallback;
+import javax.faces.component.NamingContainer;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.context.PartialViewContext;
+import javax.faces.context.PartialViewContextWrapper;
+
+import javax.portlet.faces.BridgeUtil;
+
+
+public class PortletPartialViewContextImpl extends PartialViewContextWrapper
+{
+
+ private PartialViewContext mWrapped;
+
+ private Collection<String> mExecuteIds;
+ private Collection<String> mRenderIds;
+
+ // ----------------------------------------------------------- Constructors
+
+
+ public PortletPartialViewContextImpl(PartialViewContext ctx)
+ {
+ mWrapped = ctx;
+ }
+
+
+ // ---------------------------------------------- Methods from PartialViewContext
+
+ @Override
+ public PartialViewContext getWrapped()
+ {
+ return mWrapped;
+ }
+
+
+ /**
+ * @see javax.faces.context.PartialViewContext#getExecuteIds()
+ */
+ @Override
+ public Collection<String> getExecuteIds()
+ {
+ // Merely delegate is not a portlet request
+ if (!BridgeUtil.isPortletRequest())
+ {
+ return super.getExecuteIds();
+ }
+
+
+ if (mExecuteIds != null) {
+ return mExecuteIds;
+ }
+ if (!super.isExecuteAll())
+ {
+ mExecuteIds = fixUpClientIds(super.getExecuteIds());
+ return mExecuteIds;
+ }
+ else
+ {
+ return super.getExecuteIds();
+ }
+ }
+
+ /**
+ * @see javax.faces.context.PartialViewContext#getRenderIds()
+ */
+ @Override
+ public Collection<String> getRenderIds()
+ {
+ // Merely delegate is not a portlet request
+ if (!BridgeUtil.isPortletRequest())
+ {
+ return super.getRenderIds();
+ }
+
+ if (mRenderIds != null) {
+ return mRenderIds;
+ }
+
+ if (!super.isRenderAll())
+ {
+ mRenderIds = fixUpClientIds(super.getRenderIds());
+ return mRenderIds;
+ }
+ else
+ {
+ return super.getRenderIds();
+ }
+ }
+
+
+ /**
+ * @see javax.faces.context.PartialViewContext#release()
+ */
+ public void release()
+ {
+ super.release();
+
+ mExecuteIds = null;
+ mRenderIds = null;
+ }
+
+
+ /* Ugh -- 2.0 bug -- this method not in the wrapper */
+ public void setPartialRequest(boolean b)
+ {
+ getWrapped().setPartialRequest(b);
+ }
+
+ private Collection<String> fixUpClientIds(Collection<String> ids)
+ {
+ FacesContext ctx = FacesContext.getCurrentInstance();
+ String vrId = ctx.getViewRoot().getContainerClientId(ctx);
+
+ ArrayList<String> fixedIds = new ArrayList<String>(ids.size());
+ for (String id : ids)
+ {
+ fixedIds.add(fixUpClientId(id, vrId));
+ }
+ return fixedIds;
+ }
+
+ private String fixUpClientId(String id, String bridgeVRPrefix)
+ {
+ if (!id.startsWith(bridgeVRPrefix))
+ {
+ id = new StringBuffer(bridgeVRPrefix).append(":").append(id).toString();
+ }
+ return id;
+ }
+
+ /*
+ private String fixUpClientId(String id)
+ {
+ FacesContext ctx = FacesContext.getCurrentInstance();
+ UIViewRoot vr = ctx.getViewRoot();
+
+ // First ask whether id is a valid client id by searching for it.
+ if (vr.invokeOnComponent(ctx, id, new ContextCallback() {
+ public void invokeContextCallback(FacesContext context,
+ UIComponent component)
+ {
+ }
+ }))
+ {
+ return id;
+ }
+
+ // Otherwise assume its the actual id -- find it and get its client id
+ UIComponent comp = findComponent(vr, id);
+ if (comp != null)
+ {
+ return comp.getClientId();
+ }
+ else
+ {
+ return id; // Don't know whether this id is valid or not but forge ahead
+ }
+ }
+
+ private UIComponent findComponent(UIComponent base, String searchId)
+ {
+ if (searchId.equals(base.getId())) {
+ return base;
+ }
+ UIComponent result = null;
+
+ // Search through our facets and children
+ for (Iterator i = base.getFacetsAndChildren(); i.hasNext(); )
+ {
+ result = findComponent((UIComponent) i.next(), searchId);
+
+ if (result != null) break;
+ }
+ return result;
+
+ }
+*/
+
+}
Modified: myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java?rev=1068501&r1=1068500&r2=1068501&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java (original)
+++ myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java Tue Feb 8 18:17:38 2011
@@ -38,6 +38,7 @@ public final class QueryString
private Map<String, List<Parameter>> mParameterMap;
private List<Parameter> mParameterList;
private List<String> mParameterNames;
+ private String mFragment;
/**
* Construct a <code>QueryString</code> from a pre-encoded string.
@@ -146,6 +147,11 @@ public final class QueryString
mQueryString = buff.substring(startPos);
}
+
+ if (mFragment != null)
+ {
+ mQueryString += mFragment;
+ }
}
else
{
@@ -381,6 +387,9 @@ public final class QueryString
{
if (mParameterList == null)
{
+ // remove/deal with a fragment hanging on the end
+ initFragment();
+
// TODO: Constant
mParameterList = new ArrayList<Parameter>(30);
int length;
@@ -412,6 +421,24 @@ public final class QueryString
} while (nextPos < length);
}
}
+
+ private void initFragment()
+ {
+ if (mQueryString != null)
+ {
+ int i = mQueryString.indexOf('#');
+ if (i == 0)
+ {
+ mFragment = mQueryString;
+ mQueryString = "";
+ }
+ else if (i > 0)
+ {
+ mFragment = mQueryString.substring(i);
+ mQueryString = mQueryString.substring(0, i);
+ }
+ }
+ }
private class Parameter
{
Modified: myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/URLUtils.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/URLUtils.java?rev=1068501&r1=1068500&r2=1068501&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/URLUtils.java (original)
+++ myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/URLUtils.java Tue Feb 8 18:17:38 2011
@@ -19,6 +19,9 @@
package org.apache.myfaces.portlet.faces.util;
+import java.util.List;
+import java.util.Map;
+
public class URLUtils
{
@@ -90,6 +93,72 @@ public class URLUtils
return appendURLArguments(buffer, baseURL, keysAndValues);
}
+
+
+ public static String appendURLArguments(StringBuilder buffer, String baseURL,
+ Map<String, List<String>> keysAndValues)
+ {
+
+ // Bug 1814825: the anchor has to stay on the end.
+ int anchorIndex = baseURL.indexOf('#');
+
+ if (anchorIndex >= 0)
+ {
+ buffer.append(baseURL.substring(0, anchorIndex));
+ }
+ else
+ {
+ buffer.append(baseURL);
+ }
+
+ boolean queryAppended = baseURL.indexOf('?') >= 0;
+
+ for (Map.Entry<String, List<String>> entry : keysAndValues.entrySet())
+ {
+ String key = entry.getKey();
+ List<String> values = entry.getValue();
+
+ if (values == null) continue;
+
+ for (String value : values)
+ {
+ if (value != null)
+ {
+ // only append '?' at start if the URL doesn't already contain
+ // arguments
+ if (!queryAppended)
+ {
+ queryAppended = true;
+ buffer.append('?');
+ }
+ else
+ {
+ buffer.append('&');
+ }
+
+ buffer.append(key);
+ buffer.append('=');
+ buffer.append(value);
+ }
+ }
+ }
+
+
+ String beforeEncode = buffer.toString();
+ return beforeEncode;
+ }
+
+ public static String appendURLArguments(String baseURL, Map<String, List<String>> keysAndValues)
+ {
+ if (keysAndValues != null)
+ {
+ return appendURLArguments(new StringBuilder(baseURL.length()), baseURL, keysAndValues);
+ }
+ else
+ {
+ return baseURL;
+ }
+ }
public static String convertFromRelative(String currentPath, String relativeLoc)
throws IllegalArgumentException
Modified: myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/resources/META-INF/faces-config.xml
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/resources/META-INF/faces-config.xml?rev=1068501&r1=1068500&r2=1068501&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/resources/META-INF/faces-config.xml (original)
+++ myfaces/portlet-bridge/core/trunk_3.0.x/impl/src/main/resources/META-INF/faces-config.xml Tue Feb 8 18:17:38 2011
@@ -40,5 +40,6 @@
</application>
<factory>
<exception-handler-factory>org.apache.myfaces.portlet.faces.context.PortletExceptionHanderFactoryImpl</exception-handler-factory>
+ <partial-view-context-factory>org.apache.myfaces.portlet.faces.context.PortletPartialViewContextFactoryImpl</partial-view-context-factory>
</factory>
</faces-config>