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 2009/04/29 23:48:20 UTC
svn commit: r769955 - in /myfaces/portlet-bridge/core/trunk:
api/src/main/java/javax/portlet/faces/
api/src/main/java/javax/portlet/faces/component/
impl/src/main/java/org/apache/myfaces/portlet/faces/application/
impl/src/main/java/org/apache/myfaces/...
Author: mfreedman
Date: Wed Apr 29 21:48:20 2009
New Revision: 769955
URL: http://svn.apache.org/viewvc?rev=769955&view=rev
Log:
PORTLETBRIDGE-63: Create view/ui viewroot changes
PORTLETBRIDGE-64: Wrap exceptions correctly
PORTLETBRIDGE-65: Client directed views should invalidate redirect cache
PORTLETBRIDGE-66: Client direct view: don't restore scope
PORTLETBRIDGE-67: Recursive render redirects broken
PORTLETBRIDGE-68: Temp request params not flushed
PORTLETBRIDGE-69: Improve PortletNamingContainer impl
PORTLETBRIDGE-70: GenericFacesPortlet doesn't ensure valid ContentType setting.
Added:
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletApplicationFactoryImpl.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletApplicationImpl.java
Modified:
myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/component/PortletNamingContainerUIViewRoot.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/FacesContextFactoryImpl.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java
Modified: myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java?rev=769955&r1=769954&r2=769955&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java (original)
+++ myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java Wed Apr 29 21:48:20 2009
@@ -328,12 +328,25 @@
String contentType =
getPortletConfig().getPortletContext().getInitParameter(DEFAULT_CONTENT_TYPE);
- if (contentType == null)
+ if (contentType == null || !isInRequestedContentTypes(request, contentType))
{
contentType = request.getResponseContentType();
}
return contentType;
}
+
+ private boolean isInRequestedContentTypes(PortletRequest request, String contentTypeToCheck)
+ {
+ Enumeration e = request.getResponseContentTypes();
+ while (e.hasMoreElements())
+ {
+ if (contentTypeToCheck.equalsIgnoreCase((String) e.nextElement()))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
/**
* Returns the character set encoding used for this portlet response. Subclasses override to
Modified: myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/component/PortletNamingContainerUIViewRoot.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/component/PortletNamingContainerUIViewRoot.java?rev=769955&r1=769954&r2=769955&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/component/PortletNamingContainerUIViewRoot.java (original)
+++ myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/component/PortletNamingContainerUIViewRoot.java Wed Apr 29 21:48:20 2009
@@ -10,30 +10,13 @@
*/
package javax.portlet.faces.component;
-import java.io.IOException;
import java.io.Serializable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.el.MethodExpression;
-import javax.el.ValueExpression;
-
-import javax.faces.FacesException;
-import javax.faces.component.ContextCallback;
import javax.faces.context.FacesContext;
import javax.faces.component.NamingContainer;
-import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
-import javax.faces.el.ValueBinding;
-import javax.faces.event.AbortProcessingException;
-import javax.faces.event.FacesEvent;
-import javax.faces.event.PhaseListener;
-
import javax.portlet.faces.Bridge;
import javax.portlet.faces.BridgeUtil;
import javax.portlet.faces.annotation.PortletNamingContainer;
@@ -51,59 +34,54 @@
//TODO: This should be regenerated each time this is modified. Can this be added to maven?
private static final long serialVersionUID = -4524288011655837711L;
- private static final String PORTLET_NAMESPACE_ID = Bridge.BRIDGE_PACKAGE_PREFIX + "PortletNamespaceId";
+ private static final String PORTLET_ENCODED_NAMESPACE_ID = Bridge.BRIDGE_PACKAGE_PREFIX + "PortletEncodedNamespaceId";
- private String mNamespace;
-
+ // Assumes that first use of the UIViewRoot always occurs in a render as portlet namespace
+ // is only available during a render. If this isn't the case we disable use of the
+ // NamingContainer
public PortletNamingContainerUIViewRoot()
{
super();
+
+ getAttributes().put(PORTLET_ENCODED_NAMESPACE_ID, Boolean.FALSE);
}
/**
- * Implements NamingContainer semantics. Ensures that the returned identifier
- * contains the consumer (portal) provided unique portlet id. This ensures that
- * those components in this NamingContainer generate ids which will not collide
- * in the consumer page. Implementation merely calls the static form of this
- * method.
+ * NamingContainer semantics worked generically (serviced by subclasses) as long as the class
+ * is marked as implementing NamingContainer and we use the portletNamespace Id as
+ * (part of) the component's id.
*/
@Override
public String getContainerClientId(FacesContext context)
{
- // only add NamingContainer behavior when running in a portlet request
- if (BridgeUtil.isPortletRequest())
+ if (BridgeUtil.isPortletRequest() && ((Boolean) this.getAttributes().get(PORTLET_ENCODED_NAMESPACE_ID)).equals(Boolean.TRUE))
{
-
- /* Note: In portlet 1.0 the namespace is guaranteed valid for the request it
- * was passed -- so its possible that resusing the saved one will no longer
- * be valid. However this is less likely than JSF expecting to not use the
- * clientId from here to refer to an element in the reconstructed tree --
- * Note though this is also unlikely we know of portlet 1.0 extended impls
- * that support ajax via an extended portlet 1.0 where they run the full
- * lifecycle during a render and hence need action semantics in the render
- */
- if (mNamespace != null || (mNamespace = (String) this.getAttributes().get(PORTLET_NAMESPACE_ID)) != null)
- {
- return mNamespace;
- }
+ return super.getContainerClientId(context);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ @Override
+ public void setId(String id)
+ {
+ if (BridgeUtil.isPortletRequest())
+ {
+ Boolean encoded = Boolean.FALSE;
/* Can only calculate the namespace during a render (in portlet 1.0) */
- else if (BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.RENDER_PHASE)
+ if (BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.RENDER_PHASE)
{
- ExternalContext ec = context.getExternalContext();
- mNamespace = ec.encodeNamespace("");
- // also write it as a component so it is preserved across save/restore
- // using the same value ensures consistentcy in portlet environments where
- // such a namespace varies by request
- this.getAttributes().put(PORTLET_NAMESPACE_ID, mNamespace);
- return mNamespace;
+ ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
+ id = ec.encodeNamespace("_" + id);
+ // now indicate that this id is encoded
+ encoded = Boolean.TRUE;
}
- else
- throw new NullPointerException("getContainerClientId: null portlet namespace in non-render phase");
+ getAttributes().put(PORTLET_ENCODED_NAMESPACE_ID, encoded);
}
-
- return null;
-
+ super.setId(id);
}
}
Added: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletApplicationFactoryImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletApplicationFactoryImpl.java?rev=769955&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletApplicationFactoryImpl.java (added)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletApplicationFactoryImpl.java Wed Apr 29 21:48:20 2009
@@ -0,0 +1,45 @@
+/* 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.application;
+
+import javax.faces.application.Application;
+import javax.faces.application.ApplicationFactory;
+
+
+public class PortletApplicationFactoryImpl extends ApplicationFactory
+{
+ private ApplicationFactory mHandler;
+
+ public PortletApplicationFactoryImpl(ApplicationFactory handler)
+ {
+ mHandler = handler;
+ }
+
+ public Application getApplication()
+ {
+ return new PortletApplicationImpl(mHandler.getApplication());
+ }
+
+ public void setApplication(Application app)
+ {
+ mHandler.setApplication(app);
+ }
+
+}
\ No newline at end of file
Added: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletApplicationImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletApplicationImpl.java?rev=769955&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletApplicationImpl.java (added)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletApplicationImpl.java Wed Apr 29 21:48:20 2009
@@ -0,0 +1,376 @@
+/* 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.application;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import javax.el.ELContextListener;
+import javax.el.ELException;
+import javax.el.ELResolver;
+import javax.el.ExpressionFactory;
+import javax.el.ValueExpression;
+
+import javax.faces.FacesException;
+import javax.faces.application.Application;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.el.ReferenceSyntaxException;
+
+import javax.portlet.faces.BridgeUtil;
+import javax.portlet.faces.annotation.ExcludeFromManagedRequestScope;
+import javax.portlet.faces.annotation.PortletNamingContainer;
+import javax.portlet.faces.component.PortletNamingContainerUIViewRoot;
+
+
+public class PortletApplicationImpl extends Application
+{
+ private Application mWrapped;
+
+ public PortletApplicationImpl(Application app)
+ {
+ mWrapped = app;
+ }
+
+ // The following concrete methods were added for JSF 1.2. They supply default
+ // implementations that throw UnsupportedOperationException.
+ // This allows old Application implementations to still work.
+ public void addELResolver(ELResolver resolver) {
+ mWrapped.addELResolver(resolver);
+ }
+
+ public ELResolver getELResolver() {
+ return mWrapped.getELResolver();
+ }
+
+ public ResourceBundle getResourceBundle(FacesContext ctx, String name)
+ throws FacesException, NullPointerException {
+ return mWrapped.getResourceBundle(ctx, name);
+ }
+
+ public UIComponent createComponent(ValueExpression componentExpression,
+ FacesContext facesContext,
+ String componentType)
+ throws FacesException, NullPointerException {
+ return mWrapped.createComponent(componentExpression, facesContext, componentType);
+ }
+
+ public ExpressionFactory getExpressionFactory() {
+ return mWrapped.getExpressionFactory();
+ }
+
+ public void addELContextListener(ELContextListener listener) {
+ mWrapped.addELContextListener(listener);
+ }
+
+ public void removeELContextListener(ELContextListener listener) {
+ mWrapped.removeELContextListener(listener);
+ }
+
+ public ELContextListener[] getELContextListeners() {
+ return mWrapped.getELContextListeners();
+ }
+
+ public Object evaluateExpressionGet(FacesContext context,
+ String expression,
+ Class expectedType)
+ throws ELException {
+ return mWrapped.evaluateExpressionGet(context, expression, expectedType);
+ }
+
+ public javax.faces.event.ActionListener getActionListener()
+ {
+ return mWrapped.getActionListener();
+ }
+
+ public void setActionListener(javax.faces.event.ActionListener listener)
+ {
+ mWrapped.setActionListener(listener);
+ }
+
+ public Locale getDefaultLocale()
+ {
+ return mWrapped.getDefaultLocale();
+ }
+
+ public void setDefaultLocale(Locale locale)
+ {
+ mWrapped.setDefaultLocale(locale);
+ }
+
+ public String getDefaultRenderKitId()
+ {
+ return mWrapped.getDefaultRenderKitId();
+ }
+
+ public void setDefaultRenderKitId(String renderKitId)
+ {
+ mWrapped.setDefaultRenderKitId(renderKitId);
+ }
+
+ public String getMessageBundle()
+ {
+ return mWrapped.getMessageBundle();
+ }
+
+ public void setMessageBundle(String bundle)
+ {
+ mWrapped.setMessageBundle(bundle);
+ }
+
+ /**
+ * Return the NavigationHandler object which is responsible for mapping from
+ * a logical (viewid, fromAction, outcome) to the URL of a view to be rendered.
+ */
+ public javax.faces.application.NavigationHandler getNavigationHandler()
+ {
+ return mWrapped.getNavigationHandler();
+ }
+
+ public void setNavigationHandler(javax.faces.application.NavigationHandler handler)
+ {
+ mWrapped.setNavigationHandler(handler);
+ }
+
+ /**
+ * Get the object used by the VariableResolver to read and write named properties
+ * on java beans, Arrays, Lists and Maps. This object is used by the ValueBinding
+ * implementation, and during the process of configuring "managed bean" properties.
+ *
+ * @deprecated
+ */
+ public javax.faces.el.PropertyResolver getPropertyResolver()
+ {
+ return mWrapped.getPropertyResolver();
+ }
+
+ /**
+ * @deprecated
+ */
+ public void setPropertyResolver(javax.faces.el.PropertyResolver resolver)
+ {
+ mWrapped.setPropertyResolver(resolver);
+ }
+
+ /**
+ * Get the object used to resolve expressions of form "#{...}".
+ *
+ * @deprecated
+ */
+ public javax.faces.el.VariableResolver getVariableResolver()
+ {
+ return mWrapped.getVariableResolver();
+ }
+
+ /**
+ * @deprecated
+ */
+ public void setVariableResolver(javax.faces.el.VariableResolver resolver)
+ {
+ mWrapped.setVariableResolver(resolver);
+ }
+
+ public javax.faces.application.ViewHandler getViewHandler()
+ {
+ return mWrapped.getViewHandler();
+ }
+
+ public void setViewHandler(javax.faces.application.ViewHandler handler)
+ {
+ mWrapped.setViewHandler(handler);
+ }
+
+ public javax.faces.application.StateManager getStateManager()
+ {
+ return mWrapped.getStateManager();
+ }
+
+ public void setStateManager(javax.faces.application.StateManager manager)
+ {
+ mWrapped.setStateManager(manager);
+ }
+
+ /**
+ * Define a new mapping from a logical "component type" to an actual java class name.
+ * This controls what type is created when method createComponent of this class is
+ * called.
+ * <p>
+ * Param componentClass must be the fully-qualified class name of some class
+ * extending the UIComponent class. The class must have a default constructor,
+ * as instances of it will be created using Class.newInstance.
+ * <p>
+ * It is permitted to override a previously defined mapping, ie to call this
+ * method multiple times with the same componentType string. The createComponent
+ * method will simply use the last defined mapping.
+ */
+ public void addComponent(String componentType,
+ String componentClass)
+ {
+ mWrapped.addComponent(componentType, componentClass);
+ }
+
+
+ /**
+ * Create a new UIComponent subclass, using the mappings defined by previous
+ * calls to the addComponent method of this class.
+ * <p>
+ * @throws FacesException if there is no mapping defined for the specified
+ * componentType, or if an instance of the specified type could not be
+ * created for any reason.
+ */
+ public javax.faces.component.UIComponent createComponent(String componentType)
+ throws FacesException
+ {
+ UIComponent component = mWrapped.createComponent(componentType);
+ if (BridgeUtil.isPortletRequest() &&
+ component.getClass() == UIViewRoot.class &&
+ UIViewRoot.class.getAnnotation(PortletNamingContainer.class) == null
+ )
+ {
+ // replace with our own UIViewRoot
+ component = new PortletNamingContainerUIViewRoot();
+ }
+ return component;
+ }
+
+ /**
+ * Create an object which has an associating "binding" expression tying the component
+ * to a user property.
+ * <p>
+ * First the specified value-binding is evaluated; if it returns a non-null value then
+ * the component "already exists" and so the resulting value is simply returned.
+ * <p>
+ * Otherwise a new UIComponent instance is created using the specified componentType,
+ * and the new object stored via the provided value-binding before being returned.
+ *
+ * @deprecated
+ */
+ public javax.faces.component.UIComponent createComponent(
+ javax.faces.el.ValueBinding componentBinding,
+ javax.faces.context.FacesContext context,
+ String componentType)
+ throws FacesException
+ {
+ return mWrapped.createComponent(componentBinding, context, componentType);
+ }
+
+ public Iterator<String> getComponentTypes()
+ {
+ return mWrapped.getComponentTypes();
+ }
+
+ public void addConverter(String converterId,
+ String converterClass)
+ {
+ mWrapped.addConverter(converterId, converterClass);
+ }
+
+ public void addConverter(Class targetClass,
+ String converterClass)
+ {
+ mWrapped.addConverter(targetClass, converterClass);
+ }
+
+ public javax.faces.convert.Converter createConverter(String converterId)
+ {
+ return mWrapped.createConverter(converterId);
+ }
+
+ public javax.faces.convert.Converter createConverter(Class targetClass)
+ {
+ return mWrapped.createConverter(targetClass);
+ }
+
+ public Iterator<String> getConverterIds()
+ {
+ return mWrapped.getConverterIds();
+ }
+
+ public Iterator<Class> getConverterTypes()
+ {
+ return mWrapped.getConverterTypes();
+ }
+
+ /**
+ * Create an object which can be used to invoke an arbitrary method via an
+ * EL expression at a later time. This is similar to createValueBinding
+ * except that it can invoke an arbitrary method (with parameters) rather
+ * than just get/set a javabean property.
+ * <p>
+ * This is used to invoke ActionListener method, and ValueChangeListener
+ * methods.
+ *
+ * @deprecated
+ */
+ public javax.faces.el.MethodBinding createMethodBinding(
+ String ref, Class[] params)
+ throws ReferenceSyntaxException
+ {
+ return mWrapped.createMethodBinding(ref, params);
+ }
+
+ public Iterator<Locale> getSupportedLocales()
+ {
+ return mWrapped.getSupportedLocales();
+ }
+
+ public void setSupportedLocales(Collection<Locale> locales)
+ {
+ mWrapped.setSupportedLocales(locales);
+ }
+
+ public void addValidator(String validatorId,
+ String validatorClass)
+ {
+ mWrapped.addValidator(validatorId, validatorClass);
+ }
+
+ public javax.faces.validator.Validator createValidator(String validatorId)
+ throws FacesException
+ {
+ return mWrapped.createValidator(validatorId);
+ }
+
+ public Iterator<String> getValidatorIds()
+ {
+ return mWrapped.getValidatorIds();
+ }
+
+ /**
+ * Create an object which can be used to invoke an arbitrary method via an
+ * EL expression at a later time. This is similar to createValueBinding
+ * except that it can invoke an arbitrary method (with parameters) rather
+ * than just get/set a javabean property.
+ * <p>
+ * This is used to invoke ActionListener method, and ValueChangeListener
+ * methods.
+ *
+ * @deprecated
+ */
+ public javax.faces.el.ValueBinding createValueBinding(String ref)
+ throws ReferenceSyntaxException
+ {
+ return mWrapped.createValueBinding(ref);
+ }
+
+}
\ No newline at end of file
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java?rev=769955&r1=769954&r2=769955&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java Wed Apr 29 21:48:20 2009
@@ -151,6 +151,7 @@
}
}
+
UIViewRoot viewRoot = null;
// The bridge allows viewIds to carry querystrings -- e.g. a qs that has the
@@ -161,16 +162,28 @@
int qsLoc = viewId.indexOf('?');
if (qsLoc < 0)
qsLoc = viewId.length();
-
- String prior = setUIViewRootComponent(facesContext);
- try
- {
- viewRoot = super.createView(facesContext, viewId.substring(0, qsLoc));
- }
- finally
+
+ viewRoot = super.createView(facesContext, viewId.substring(0, qsLoc));
+
+ // As we have provided an ApplicationImpl to override createComponent
+ // to detect when to swap in our NamingContainer the returned viewRoot
+ // from above should already be the one we want. Because its possible
+ // its still the native UIViewRoot -- i.e. createComponent wasn't called
+ // the following code checks/and does the right thing to satisfy the spec.
+
+ if (viewRoot.getClass() == UIViewRoot.class &&
+ UIViewRoot.class.getAnnotation(PortletNamingContainer.class) == null)
{
- if (prior != null)
- resetUIViewRootComponent(facesContext, prior);
+ String prior = setUIViewRootComponent(facesContext);
+ try
+ {
+ viewRoot = super.createView(facesContext, viewId.substring(0, qsLoc));
+ }
+ finally
+ {
+ if (prior != null)
+ resetUIViewRootComponent(facesContext, prior);
+ }
}
if (qsLoc < viewId.length())
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java?rev=769955&r1=769954&r2=769955&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java Wed Apr 29 21:48:20 2009
@@ -118,7 +118,7 @@
private static final String REQUEST_SCOPE_ID_RENDER_PARAM = "__jpfbReqScopeId";
private static final int DEFAULT_MAX_MANAGED_REQUEST_SCOPES = 100;
- private Boolean mPreserveActionParams = false;
+ private Boolean mPreserveActionParams = Boolean.FALSE;
private List<String> mExcludedRequestAttributes = null;
private PortletConfig mPortletConfig = null;
@@ -189,7 +189,12 @@
// portletConfig to any newly created contexts.
ApplicationFactory appFactory =
(ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
+
+ // Wrapped desired Application with our own to override createComponent and
+ // insert our NamingContainerUIViewRoot component. This was done through
+ // configuration via the META-INF/service/javax.faces.application.ApplicationFactory
Application app = appFactory.getApplication();
+
app.addELContextListener(this);
// Process and cache the FacesServlet mappings for use by
@@ -335,13 +340,9 @@
mPortletConfig.getPortletContext().log("Exception thrown in doFacesRequest:action", e);
if (!(e instanceof BridgeException))
{
- Throwable rootCause = e.getCause();
- throw new BridgeException(e.getMessage(), rootCause);
- }
- else
- {
- throw (BridgeException) e;
+ e = new BridgeException(e);
}
+ throw (BridgeException) e;
}
finally
{
@@ -453,18 +454,26 @@
// we need to remove all but these preexisting ones.
List<String> preExistingAttributes = getRequestAttributes(request);
+ // Now we need to determine if view we are going to render is the one
+ // encoded in the request (parameters) or specifically supplied
+ // either by the portlet itself or by a prior render redirect.
+ boolean clientDirectedView = ((request.getAttribute(Bridge.VIEW_ID) != null) ||
+ (request.getAttribute(Bridge.VIEW_PATH) != null));
+
// Now check to see if this is a Refresh (render) that follows a redirect
// If it is use the redirect information cached in the session as the basis
// for the request.
QueryString redirectParams = (QueryString)
request.getPortletSession(true).getAttribute(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS);
+
+ boolean modeChanged = hasModeChanged(request, redirectParams);
- if (redirectParams != null && hasModeChanged(request, redirectParams))
+ if (redirectParams != null && (clientDirectedView || modeChanged))
{
// if we are too rely on the render redirect cache we must still
- // be in the same mode
+ // be in the same mode and/or the portlet can't have set an explicit view to use
- // mode change while in redirectDuringRender state
+ // mode change/direct view set while in redirectDuringRender state
// clear this state (as we are no longer in it)
// and don't use the data
redirectParams = null;
@@ -473,14 +482,14 @@
}
- // never restore a scope if relying on render redirect cache
- if (redirectParams == null)
+ // never restore a scope if relying on render redirect cache/client directed view/mode change
+ if (redirectParams == null && !clientDirectedView)
{
// If available -- restore the bridge request scope before getting the
// FacesContext in case anything in the context construction relies
// on these restored values.
// don't restore scope if mode changed
- scopeId = request.getParameter(REQUEST_SCOPE_ID_RENDER_PARAM);;
+ scopeId = request.getParameter(REQUEST_SCOPE_ID_RENDER_PARAM);
if (scopeId != null)
{
// Its possible we didn't detect the mode change but its the wrong scope
@@ -553,13 +562,9 @@
mPortletConfig.getPortletContext().log("Exception thrown in doFacesRequest:render: " + e.getMessage() + " : " + e.toString());
if (!(e instanceof BridgeException))
{
- Throwable rootCause = e.getCause();
- throw new BridgeException(e.getMessage(), rootCause);
- }
- else
- {
- throw (BridgeException) e;
+ e = new BridgeException(e);
}
+ throw (BridgeException) e;
}
finally
{
@@ -916,12 +921,24 @@
// start a new FacesContext
context = getFacesContext(request, response, lifecycle, redirectParams);
+ // Deal with possible recursion by clearing the cache, then calling doFacesRender
+ // to render the redirect, and then finally setting the cache, if its hasn't
+ // already been set. In the (recursive) multi-render redirect case, the
+ // last redirect will be the only one that sets the cache.
+ context.getExternalContext().getSessionMap().remove(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS);
+
// Run lifecycle.execute again ... then render
doFacesRender(request, response, context, lifecycle, null, preExistingAttrs);
+ // Reacquire the context as it may have changed if a recursive redirect render occurred
+ context = FacesContext.getCurrentInstance();
+
// now cache the (last) redirect params on session for resuse in subsequent renders
// that occur before an action
- context.getExternalContext().getSessionMap().put(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS, redirectParams);
+ if (context.getExternalContext().getSessionMap().get(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS) == null)
+ {
+ context.getExternalContext().getSessionMap().put(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS, redirectParams);
+ }
}
@@ -939,8 +956,7 @@
}
catch (FacesException e)
{
- Throwable rootCause = e.getCause();
- throw new BridgeException(e.getMessage(), rootCause);
+ throw new BridgeException(e);
}
}
@@ -984,8 +1000,7 @@
}
catch (FacesException e)
{
- Throwable rootCause = e.getCause();
- throw new BridgeException(e.getMessage(), rootCause);
+ throw new BridgeException(e);
}
}
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/FacesContextFactoryImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/FacesContextFactoryImpl.java?rev=769955&r1=769954&r2=769955&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/FacesContextFactoryImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/FacesContextFactoryImpl.java Wed Apr 29 21:48:20 2009
@@ -19,12 +19,7 @@
package org.apache.myfaces.portlet.faces.context;
-import java.util.Iterator;
-
import javax.faces.FacesException;
-import javax.faces.application.Application;
-import javax.faces.component.UIComponent;
-import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
@@ -32,9 +27,6 @@
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import javax.portlet.faces.Bridge;
-import javax.portlet.faces.annotation.PortletNamingContainer;
-
-import javax.portlet.faces.component.PortletNamingContainerUIViewRoot;
import javax.servlet.ServletRequest;
@@ -67,7 +59,7 @@
if (context instanceof PortletContext && request instanceof PortletRequest
&& response instanceof PortletResponse)
{
- return new PortletFacesContextImpl(
+ return new PortletFacesContextImpl(
new PortletExternalContextImpl((PortletContext) context,
(PortletRequest) request,
(PortletResponse) response),
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java?rev=769955&r1=769954&r2=769955&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java Wed Apr 29 21:48:20 2009
@@ -28,6 +28,7 @@
import java.security.Principal;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -120,9 +121,9 @@
private Map<String, String> mInitParameterMap = null;
// maps for internal parameters (eg, those specified in query string of
- // any defaultViewId)
- private Map<String, String> mInternalRequestParameterMap = Collections.emptyMap();
- private Map<String, String[]> mInternalRequestParameterValuesMap = Collections.emptyMap();
+ // any defaultViewId) --
+ private Map<String, String> mTempExtraRequestParameterMap = Collections.emptyMap();
+ private Map<String, String[]> mTempExtraRequestParameterValuesMap = Collections.emptyMap();
private PortletRequestHeaders mPortletRequestHeaders = null;
@@ -652,9 +653,15 @@
{
if (mRequestParameterMap == null)
{
+ // In cases where the viewId is derived from either an attribute set by the portlet
+ // or from the defaultView Map, the viewId can contain additional querystring parameters.
+ // These are held by the ExternalContext in an internal temp Map until this method
+ // is called.
mRequestParameterMap =
Collections.unmodifiableMap(new PortletRequestParameterMap(mPortletRequest,
- mInternalRequestParameterMap));
+ mTempExtraRequestParameterMap));
+ // Now that it has been used/added -- clear the temp holder as its no longer needed
+ mTempExtraRequestParameterMap = null;
}
return mRequestParameterMap;
}
@@ -663,9 +670,15 @@
{
if (mRequestParameterValuesMap == null)
{
+ // In cases where the viewId is derived from either an attribute set by the portlet
+ // or from the defaultView Map, the viewId can contain additional querystring parameters.
+ // These are held by the ExternalContext in an internal temp Map until this method
+ // is called.
mRequestParameterValuesMap =
Collections.unmodifiableMap(new PortletRequestParameterValuesMap(mPortletRequest,
- mInternalRequestParameterValuesMap));
+ mTempExtraRequestParameterValuesMap));
+ // Now that it has been used/added -- clear the temp holder as its no longer needed
+ mTempExtraRequestParameterValuesMap = null;
}
return mRequestParameterValuesMap;
}
@@ -1219,16 +1232,33 @@
queryStr = new QueryString(viewId.substring(queryStart + 1), "UTF8");
// TODO: Constants
- mInternalRequestParameterMap = new HashMap<String, String>(5);
- mInternalRequestParameterValuesMap = new HashMap<String, String[]>(5);
+ // We store these into a temporary Map until a client calls the corresponding
+ // ExternalContext public api to get the request parameter map(s). In those
+ // methods we use these temp maps to build the overall Map that is returned.
+ // This roundabout technique is used to delay accessing request parameters until the
+ // client first requests them.
+ mTempExtraRequestParameterMap = new HashMap<String, String>(5);
+ mTempExtraRequestParameterValuesMap = new HashMap<String, String[]>(5);
+ // Clear any existing Request ParameterMap to ensure reconstruction
+ // with these new extra entries.
+ mRequestParameterMap = null;
+ mRequestParameterValuesMap = null;
Enumeration<String> list = queryStr.getParameterNames();
while (list.hasMoreElements())
{
String param = list.nextElement();
- mInternalRequestParameterMap.put(param, queryStr.getParameter(param));
- mInternalRequestParameterValuesMap.put(param, new String[]
- { queryStr.getParameter(param) });
+ mTempExtraRequestParameterMap.put(param, queryStr.getParameter(param));
+
+ // Now deal with the multiValue case
+ Enumeration<String> e = queryStr.getParameterValues(param);
+ ArrayList<String> l = new ArrayList(5);
+ while (e.hasMoreElements())
+ {
+ l.add(e.nextElement());
+ }
+ String[] values = new String[l.size()];
+ mTempExtraRequestParameterValuesMap.put(param, l.toArray(values));
}
viewId = viewId.substring(0, queryStart);
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java?rev=769955&r1=769954&r2=769955&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java Wed Apr 29 21:48:20 2009
@@ -21,6 +21,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -45,7 +46,7 @@
}
else
{
- mInternalAttributes = internal;
+ mInternalAttributes = new HashMap(internal);
}
}
else
@@ -59,13 +60,15 @@
{
if (mPortletRequest != null)
{
- String value = mInternalAttributes.get(key);
+ // Read from the request before the internal ones ass these are the one's
+ // specifically sent by the client.
+ String value = mPortletRequest.getParameter(key);
if (value != null)
{
return value;
}
- return mPortletRequest.getParameter(key);
+ return mInternalAttributes.get(key);
}
else
{
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java?rev=769955&r1=769954&r2=769955&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java Wed Apr 29 21:48:20 2009
@@ -21,6 +21,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -45,7 +46,7 @@
}
else
{
- mInternalAttributes = internal;
+ mInternalAttributes = new HashMap(internal);
}
}
else
@@ -59,13 +60,13 @@
{
if (mPortletRequest != null)
{
- String[] value = mInternalAttributes.get(key);
+ String[] value = mPortletRequest.getParameterValues(key);
if (value != null)
{
return value;
}
- return mPortletRequest.getParameterValues(key);
+ return mInternalAttributes.get(key);
}
else
{