Author: mrdon
Date: Mon Sep 4 23:40:29 2006
New Revision: 440278
URL: http://svn.apache.org/viewvc?view=rev&rev=440278
Log:
Enhancing jsf variable resolver to look in stack, added ability to
configure jsf from struts.xml, added support for more struts-like
navigation for jsf result, updated to new jetty plugin, fixed bad unit
test in blank app
WW-1415
WW-1416
WW-1414
WW-1349
--This line, and those below, will be ignored--
M apps/starter/pom.xml
M apps/blank/src/test/java/example/WelcomeTest.java
M apps/showcase/pom.xml
M core/src/main/java/org/apache/struts2/jsf/FacesResult.java
M core/src/main/java/org/apache/struts2/jsf/FacesSetupInterceptor.java
AM core/src/main/java/org/apache/struts2/jsf/FacesRender.java
M core/src/main/java/org/apache/struts2/jsf/StrutsVariableResolver.java
M core/src/main/resources/struts-default.xml
Added:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesRender.java
(with props)
Modified:
struts/struts2/trunk/apps/blank/src/test/java/example/WelcomeTest.java
struts/struts2/trunk/apps/showcase/pom.xml
struts/struts2/trunk/apps/starter/pom.xml
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesResult.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesSetupInterceptor.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/StrutsVariableResolver.java
struts/struts2/trunk/core/src/main/resources/struts-default.xml
Modified: struts/struts2/trunk/apps/blank/src/test/java/example/WelcomeTest.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/apps/blank/src/test/java/example/WelcomeTest.java?view=diff&rev=440278&r1=440277&r2=440278
==============================================================================
--- struts/struts2/trunk/apps/blank/src/test/java/example/WelcomeTest.java
(original)
+++ struts/struts2/trunk/apps/blank/src/test/java/example/WelcomeTest.java Mon
Sep 4 23:40:29 2006
@@ -28,9 +28,9 @@
public class WelcomeTest extends TestCase {
public void testWelcome() throws Exception {
- Action welcome = new Welcome();
+ Welcome welcome = new Welcome();
String result = welcome.execute();
- assertTrue(ActionSupport.SUCCESS.equals(result));
- assertTrue(welcome.equals(Welcome.MESSAGE));
+ assertEquals(ActionSupport.SUCCESS, result);
+ assertEquals(welcome.getMessage(), Welcome.MESSAGE);
}
}
Modified: struts/struts2/trunk/apps/showcase/pom.xml
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/apps/showcase/pom.xml?view=diff&rev=440278&r1=440277&r2=440278
==============================================================================
--- struts/struts2/trunk/apps/showcase/pom.xml (original)
+++ struts/struts2/trunk/apps/showcase/pom.xml Mon Sep 4 23:40:29 2006
@@ -68,7 +68,8 @@
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
- <artifactId>maven-jetty6-plugin</artifactId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <version>6.0.0rc3</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
Modified: struts/struts2/trunk/apps/starter/pom.xml
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/apps/starter/pom.xml?view=diff&rev=440278&r1=440277&r2=440278
==============================================================================
--- struts/struts2/trunk/apps/starter/pom.xml (original)
+++ struts/struts2/trunk/apps/starter/pom.xml Mon Sep 4 23:40:29 2006
@@ -26,7 +26,8 @@
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
- <artifactId>maven-jetty6-plugin</artifactId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <version>6.0.0rc3</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
Added:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesRender.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesRender.java?view=auto&rev=440278
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesRender.java
(added)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesRender.java
Mon Sep 4 23:40:29 2006
@@ -0,0 +1,76 @@
+/*
+ * $Id: PlainTextResult.java 394468 2006-04-16 12:16:03Z tmjee $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.struts2.jsf;
+
+import java.io.IOException;
+
+import javax.faces.FacesException;
+import javax.faces.application.Application;
+import javax.faces.application.ViewHandler;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+
+/**
+ * Performs the JSF render lifecycle phase.
+ *
+ */
+public class FacesRender extends FacesSupport {
+
+ /**
+ * Executes the render phase, borrowed from MyFaces
+ *
+ * @param facesContext
+ * The faces context
+ * @throws FacesException
+ * If anything goes wrong
+ */
+ public void render(FacesContext facesContext) throws FacesException {
+ // if the response is complete we should not be invoking the phase
+ // listeners
+ if (isResponseComplete(facesContext, "render", true)) {
+ return;
+ }
+ if (log.isTraceEnabled())
+ log.trace("entering renderResponse");
+
+ informPhaseListenersBefore(facesContext, PhaseId.RENDER_RESPONSE);
+ try {
+ // also possible that one of the listeners completed the response
+ if (isResponseComplete(facesContext, "render", true)) {
+ return;
+ }
+ Application application = facesContext.getApplication();
+ ViewHandler viewHandler = application.getViewHandler();
+ try {
+ viewHandler
+ .renderView(facesContext, facesContext.getViewRoot());
+ } catch (IOException e) {
+ throw new FacesException(e.getMessage(), e);
+ }
+ } finally {
+ informPhaseListenersAfter(facesContext, PhaseId.RENDER_RESPONSE);
+ }
+ if (log.isTraceEnabled()) {
+ // Note: DebugUtils Logger must also be in trace level
+ // DebugUtils.traceView("View after rendering");
+ }
+
+ if (log.isTraceEnabled())
+ log.trace("exiting renderResponse");
+ }
+}
Propchange:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesRender.java
------------------------------------------------------------------------------
svn:executable = *
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesResult.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesResult.java?view=diff&rev=440278&r1=440277&r2=440278
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesResult.java
(original)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesResult.java
Mon Sep 4 23:40:29 2006
@@ -17,13 +17,11 @@
*/
package org.apache.struts2.jsf;
-import java.io.IOException;
-
-import javax.faces.FacesException;
-import javax.faces.application.Application;
import javax.faces.application.ViewHandler;
+import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
-import javax.faces.event.PhaseId;
+
+import org.apache.struts2.dispatcher.StrutsResultSupport;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
@@ -31,58 +29,46 @@
/**
* Executes the JSF render phase
*/
-public class FacesResult extends FacesSupport implements Result {
+public class FacesResult extends StrutsResultSupport implements Result {
private static final long serialVersionUID = -3548970638740937804L;
/**
- * Executes the result
+ * Checks to see if we need to build a new JSF ViewId from the Struts
Result
+ * config and then renders the result by delegating to the
+ * FacesRender.render().
+ *
+ * @see
org.apache.struts2.dispatcher.StrutsResultSupport#doExecute(java.lang.String,
+ * com.opensymphony.
*/
- public void execute(ActionInvocation invocation) throws Exception {
- render(FacesContext.getCurrentInstance());
+ protected void doExecute(String finalLocation, ActionInvocation invocation)
+ throws Exception {
+ performNavigation(finalLocation, FacesContext.getCurrentInstance());
+ new FacesRender().render(FacesContext.getCurrentInstance());
}
/**
- * Executes the render phase, borrowed from MyFaces
+ * Compares the Struts Result uri to the faces viewId. If they are
different
+ * use the Struts uri to build a new faces viewId.
*
+ * @param finalLocation
+ * The result uri
* @param facesContext
- * The faces context
- * @throws FacesException
- * If anything goes wrong
+ * The FacesContext
*/
- public void render(FacesContext facesContext) throws FacesException {
- // if the response is complete we should not be invoking the phase
- // listeners
- if (isResponseComplete(facesContext, "render", true)) {
- return;
- }
- if (log.isTraceEnabled())
- log.trace("entering renderResponse");
-
- informPhaseListenersBefore(facesContext, PhaseId.RENDER_RESPONSE);
- try {
- // also possible that one of the listeners completed the response
- if (isResponseComplete(facesContext, "render", true)) {
- return;
- }
- Application application = facesContext.getApplication();
- ViewHandler viewHandler = application.getViewHandler();
- try {
- viewHandler
- .renderView(facesContext, facesContext.getViewRoot());
- } catch (IOException e) {
- throw new FacesException(e.getMessage(), e);
+ private void performNavigation(String finalLocation,
+ FacesContext facesContext) {
+ String facesViewId = facesContext.getViewRoot().getViewId();
+ if (finalLocation != null) {
+ if (finalLocation.equals(facesViewId) == false) {
+ ViewHandler viewHandler = facesContext.getApplication()
+ .getViewHandler();
+ UIViewRoot viewRoot = viewHandler.createView(facesContext,
+ finalLocation);
+ facesContext.setViewRoot(viewRoot);
+ facesContext.renderResponse();
}
- } finally {
- informPhaseListenersAfter(facesContext, PhaseId.RENDER_RESPONSE);
}
- if (log.isTraceEnabled()) {
- // Note: DebugUtils Logger must also be in trace level
- // DebugUtils.traceView("View after rendering");
- }
-
- if (log.isTraceEnabled())
- log.trace("exiting renderResponse");
}
}
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesSetupInterceptor.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesSetupInterceptor.java?view=diff&rev=440278&r1=440277&r2=440278
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesSetupInterceptor.java
(original)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/FacesSetupInterceptor.java
Mon Sep 4 23:40:29 2006
@@ -17,15 +17,30 @@
*/
package org.apache.struts2.jsf;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
+import javax.faces.application.NavigationHandler;
+import javax.faces.application.StateManager;
+import javax.faces.application.ViewHandler;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
+import javax.faces.el.PropertyResolver;
+import javax.faces.el.VariableResolver;
+import javax.faces.event.ActionListener;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsException;
+import org.apache.struts2.util.ClassLoaderUtils;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
@@ -34,102 +49,205 @@
import com.opensymphony.xwork2.interceptor.Interceptor;
/**
- * Initializes the JSF context for this request
+ * * Initializes the JSF context for this request.
+ * <p>
+ * </P>
+ * The JSF Application can additionaly be configured from the Struts.xml by
+ * adding <param> tags to the jsfSetup <interceptor-ref>.
+ * <p>
+ * </p>
+ * <b>Example struts.xml configuration:</b>
+ *
+ * <pre>
+ * <interceptor-ref name="jsfSetup">
+ * <param name="actionListener"></param>
+ * <param name="defaultRenderKitId"></param>
+ * <param name="supportedLocale"></param>
+ * <param name="defaultLocale"></param>
+ * <param name="messageBundle"></param>
+ * <param
name="navigationHandler">org.apache.struts2.jsf.StrutsNavigationHandler</param>
+ * <param name="propertyResolver"></param>
+ * <param name="stateManager"></param>
+ * <param name="variableResolver">
+ * org.apache.myfaces.el.VariableResolverImpl
+ * ,org.apache.struts2.jsf.StrutsVariableResolver
+ * </param>
+ * <param
name="viewHandler;">org.apache.shale.tiles.TilesViewHandler</param>
+ * </interceptor-ref>
+ * </pre>
+ *
+ * <p>
+ * </p>
+ * <b>Note: None of the parameters are required but all are shown in the
example
+ * for completeness.</b>
*/
public class FacesSetupInterceptor extends FacesSupport implements Interceptor
{
- private static final long serialVersionUID = -621512342655103941L;
+ private static final long serialVersionUID = -621512342655103941L;
+
+ private String lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE;
+
+ private FacesContextFactory facesContextFactory;
+
+ private Lifecycle lifecycle;
+
+ // jsf Application configuration
+ private List<String> actionListener;
+
+ private String defaultRenderKitId;
+
+ private List<String> supportedLocale;
+
+ private String defaultLocale;
+
+ private String messageBundle;
+
+ private List<String> navigationHandler;
+
+ private List<String> propertyResolver;
+
+ private List<String> stateManager;
+
+ private List<String> variableResolver;
+
+ private List<String> viewHandler;
+
+ /**
+ * Sets the lifecycle id
+ *
+ * @param id
+ * The id
+ */
+ public void setLifecycleId(String id) {
+ this.lifecycleId = id;
+ }
+
+ /**
+ * Initializes the lifecycle and factories
+ */
+ public void init() {
+ try {
+ facesContextFactory = (FacesContextFactory) FactoryFinder
+ .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
+ } catch (Exception ex) {
+ log.debug("Unable to initialize faces", ex);
+ }
- private String lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE;
- private FacesContextFactory facesContextFactory;
- private Lifecycle lifecycle;
-
- /**
- * Sets the lifecycle id
- *
- * @param id The id
- */
- public void setLifecycleId(String id) {
- this.lifecycleId = id;
- }
-
- /**
- * Initializes the lifecycle and factories
- */
- public void init() {
- try {
- facesContextFactory = (FacesContextFactory)
FactoryFinder
-
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
- } catch (Exception ex) {
- log.debug("Unable to initialize faces", ex);
- }
-
- if (facesContextFactory == null) {
- log.info("Unable to initialize jsf interceptors
probably due missing JSF framework initialization");
- return;
- }
- // Javadoc says: Lifecycle instance is shared across multiple
- // simultaneous requests, it must be implemented in a
thread-safe
- // manner.
- // So we can acquire it here once:
- LifecycleFactory lifecycleFactory = (LifecycleFactory)
FactoryFinder
- .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
- lifecycle = lifecycleFactory.getLifecycle(lifecycleId);
-
- Application application = ((ApplicationFactory) FactoryFinder
- .getFactory(FactoryFinder.APPLICATION_FACTORY))
- .getApplication();
- if (!(application.getNavigationHandler() instanceof
StrutsNavigationHandler)) {
- application.setNavigationHandler(new
StrutsNavigationHandler(
- application.getNavigationHandler()));
- }
- if (!(application.getVariableResolver() instanceof
StrutsVariableResolver)) {
- application.setVariableResolver(new
StrutsVariableResolver(
- application.getVariableResolver()));
- }
- }
-
- /**
- * Creates the faces context for other phases.
- *
- * @param invocation
- * The action invocation
- */
- public String intercept(ActionInvocation invocation) throws Exception {
+ if (facesContextFactory == null) {
+ log
+ .info("Unable to initialize jsf interceptors probably due
missing JSF framework initialization");
+ return;
+ }
+ // Javadoc says: Lifecycle instance is shared across multiple
+ // simultaneous requests, it must be implemented in a thread-safe
+ // manner.
+ // So we can acquire it here once:
+ LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
+ .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
+ lifecycle = lifecycleFactory.getLifecycle(lifecycleId);
+
+ Application application = ((ApplicationFactory) FactoryFinder
+ .getFactory(FactoryFinder.APPLICATION_FACTORY))
+ .getApplication();
+
+ if (actionListener != null) {
+ Iterator i = actionListener.iterator();
+ application
+ .setActionListener((ActionListener) getApplicationObject(
+ ActionListener.class, i, application
+ .getActionListener()));
+ }
+ if (defaultRenderKitId != null && defaultRenderKitId.length() > 0) {
+ application.setDefaultRenderKitId(defaultRenderKitId);
+ }
+ if (messageBundle != null && messageBundle.length() > 0) {
+ application.setMessageBundle(messageBundle);
+ }
+ if (supportedLocale != null) {
+ List<Locale> locales = new ArrayList<Locale>();
+ for (Iterator i = supportedLocale.iterator(); i.hasNext();) {
+ locales.add(toLocale((String) i.next()));
+ }
+ application.setSupportedLocales(locales);
+ }
+ if (defaultLocale != null && defaultLocale.length() > 0) {
+ application.setDefaultLocale(toLocale(defaultLocale));
+ }
+ if (navigationHandler != null) {
+ Iterator i = navigationHandler.iterator();
+ application
+ .setNavigationHandler((NavigationHandler)
getApplicationObject(
+ NavigationHandler.class, i, application
+ .getNavigationHandler()));
+ }
+ if (propertyResolver != null) {
+ Iterator i = propertyResolver.iterator();
+ application
+ .setPropertyResolver((PropertyResolver)
getApplicationObject(
+ PropertyResolver.class, i, application
+ .getPropertyResolver()));
+ }
+ if (stateManager != null) {
+ Iterator i = stateManager.iterator();
+ application.setStateManager((StateManager) getApplicationObject(
+ StateManager.class, i, application.getStateManager()));
+ }
+ if (variableResolver != null) {
+ Iterator i = variableResolver.iterator();
+ application
+ .setVariableResolver((VariableResolver)
getApplicationObject(
+ VariableResolver.class, i, application
+ .getVariableResolver()));
+ }
+ if (viewHandler != null) {
+ Iterator i = viewHandler.iterator();
+ application.setViewHandler((ViewHandler) getApplicationObject(
+ ViewHandler.class, i, application.getViewHandler()));
+ }
+ }
+
+ /**
+ * Creates the faces context for other phases.
+ *
+ * @param invocation
+ * The action invocation
+ */
+ public String intercept(ActionInvocation invocation) throws Exception {
if (facesContextFactory != null && isFacesAction(invocation)) {
-
+
invocation.getInvocationContext().put(
FacesInterceptor.FACES_ENABLED, Boolean.TRUE);
-
- FacesContext facesContext =
facesContextFactory.getFacesContext(
-
ServletActionContext.getServletContext(), ServletActionContext
- .getRequest(),
ServletActionContext.getResponse(),
- lifecycle);
-
- setLifecycle(lifecycle);
-
- try {
- return invocation.invoke();
- } finally {
- facesContext.release();
- }
+
+ FacesContext facesContext = facesContextFactory.getFacesContext(
+ ServletActionContext.getServletContext(),
+ ServletActionContext.getRequest(), ServletActionContext
+ .getResponse(), lifecycle);
+
+ setLifecycle(lifecycle);
+
+ try {
+ return invocation.invoke();
+ } finally {
+ facesContext.release();
+ }
} else {
return invocation.invoke();
}
- }
-
- /**
- * Cleans up the lifecycle and factories
- */
- public void destroy() {
- facesContextFactory = null;
- lifecycle = null;
- }
-
+ }
+
+ /**
+ * Cleans up the lifecycle and factories
+ */
+ public void destroy() {
+ facesContextFactory = null;
+ lifecycle = null;
+ }
+
/**
* Determines if this action mapping will be have a JSF view
*
- * @param inv The action invocation
+ * @param inv
+ * The action invocation
* @return True if the JSF interceptors should fire
*/
protected boolean isFacesAction(ActionInvocation inv) {
@@ -140,7 +258,9 @@
try {
resClass = Class.forName(resultConfig.getClassName());
} catch (ClassNotFoundException ex) {
- log.warn("Can't find result class, ignoring as a faces
request", ex);
+ log.warn(
+ "Can't find result class, ignoring as a faces request",
+ ex);
}
if (resClass != null) {
if (resClass.isAssignableFrom(FacesResult.class)) {
@@ -149,5 +269,317 @@
}
}
return false;
+ }
+
+ /**
+ * Constructs an object from a list of class names. This method supports
+ * creating the objects using constructor delegation, if the requested
class
+ * supports it. Classes will be imbedded from top to bottom in the list
with
+ * the last class listed being the one that will be returned.
+ *
+ * @param interfaceClass
+ * The Class type that is expected to be returned
+ * @param classNamesIterator
+ * An Iterator for a list of Strings that represent the class
+ * names
+ * @param defaultObject
+ * The current Object that the jsf Application has set
+ * @return
+ */
+ private Object getApplicationObject(Class interfaceClass,
+ Iterator classNamesIterator, Object defaultObject) {
+ Object current = defaultObject;
+
+ while (classNamesIterator.hasNext()) {
+ String implClassName = (String) classNamesIterator.next();
+ Class implClass = null;
+
+ try {
+ implClass = ClassLoaderUtils.loadClass(implClassName, this
+ .getClass());
+ } catch (ClassNotFoundException e1) {
+ throw new IllegalArgumentException("Class " + implClassName
+ + " was not found.");
+ }
+
+ // check, if class is of expected interface type
+ if (!interfaceClass.isAssignableFrom(implClass)) {
+ throw new IllegalArgumentException("Class " + implClassName
+ + " is no " + interfaceClass.getName());
+ }
+
+ if (current == null) {
+ // nothing to decorate
+ try {
+ current = implClass.newInstance();
+ } catch (InstantiationException e) {
+ log.error(e.getMessage(), e);
+ throw new StrutsException(e);
+ } catch (IllegalAccessException e) {
+ log.error(e.getMessage(), e);
+ throw new StrutsException(e);
+ }
+ } else {
+ // let's check if class supports the decorator pattern
+ try {
+ Constructor delegationConstructor = implClass
+ .getConstructor(new Class[] { interfaceClass });
+ // impl class supports decorator pattern,
+ try {
+ // create new decorator wrapping current
+ current = delegationConstructor
+ .newInstance(new Object[] { current });
+ } catch (InstantiationException e) {
+ log.error(e.getMessage(), e);
+ throw new StrutsException(e);
+ } catch (IllegalAccessException e) {
+ log.error(e.getMessage(), e);
+ throw new StrutsException(e);
+ } catch (InvocationTargetException e) {
+ log.error(e.getMessage(), e);
+ throw new StrutsException(e);
+ }
+ } catch (NoSuchMethodException e) {
+ // no decorator pattern support
+ try {
+ current = implClass.newInstance();
+ } catch (InstantiationException e1) {
+ log.error(e.getMessage(), e);
+ throw new StrutsException(e);
+ } catch (IllegalAccessException e1) {
+ log.error(e.getMessage(), e);
+ throw new StrutsException(e);
+ }
+ }
+ }
+ }
+
+ return current;
+ }
+
+ /**
+ * Takes a comma delimited string of class names and stores the names in an
+ * <code>ArrayList</code>. The incoming <code>String</code> will be
+ * cleaned of any whitespace characters before the class names are stored.
+ *
+ * @param actionListener
+ * A comma delimited string of class names
+ */
+ public void setActionListener(String actionListener) {
+ if (this.actionListener == null) {
+ this.actionListener = new ArrayList<String>();
+ }
+ String clean = actionListener.replaceAll("[ \t\r\n]", "");
+ String[] actionListenerNames = clean.split(",");
+
+ for (int i = 0; i < actionListenerNames.length; i++) {
+ this.actionListener.add(actionListenerNames[i]);
+ }
+ }
+
+ /**
+ * A <code>String</code> to be used as the defaultRenderKitId for the jsf
+ * application. The incoming <code>String</code> will be cleaned of
+ * whitespace characters.
+ *
+ * @param defaultRenderKitId
+ * The defaultRenderKitId
+ */
+ public void setDefaultRenderKitId(String defaultRenderKitId) {
+ String clean = defaultRenderKitId.replaceAll("[ \t\r\n]", "");
+ this.defaultRenderKitId = clean;
+ }
+
+ /**
+ * Takes a comma delimited string of local names and stores the names in an
+ * <code>ArrayList</code>. The incoming <code>String</code> will be
+ * cleaned of any whitespace characters before the class names are stored.
+ *
+ * @param supportedLocale
+ * A comma delimited string of local names
+ */
+ public void setSupportedLocale(String supportedLocale) {
+ if (this.supportedLocale == null) {
+ this.supportedLocale = new ArrayList<String>();
+ }
+ String clean = supportedLocale.replaceAll("[ \t\r\n]", "");
+ String[] supportedLocaleNames = clean.split(",");
+
+ for (int i = 0; i < supportedLocaleNames.length; i++) {
+ this.supportedLocale.add(supportedLocaleNames[i]);
+ }
+ }
+
+ /**
+ * Stores a String representation of the defaultLocale. The incoming
+ * <code>String</code> will be cleaned of any whitespace characters before
+ * the class names are stored.
+ *
+ * @param defaultLocale
+ * The default local
+ */
+ public void setDefaultLocale(String defaultLocale) {
+ String clean = defaultLocale.replaceAll("[ \t\r\n]", "");
+ this.defaultLocale = clean;
+ }
+
+ /**
+ * Stores the messageBundle to be used to configure the jsf Application.
+ *
+ * @param messageBundle
+ * The messageBundle
+ */
+ public void setMessageBundle(String messageBundle) {
+ String clean = messageBundle.replaceAll("[ \t\r\n]", "");
+ this.messageBundle = clean;
+ }
+
+ /**
+ * Takes a comma delimited string of class names and stores the names in an
+ * <code>ArrayList</code>. The incoming <code>String</code> will be
+ * cleaned of any whitespace characters before the class names are stored.
+ *
+ * @param navigationHandlerName
+ * A comma delimited string of class names
+ */
+ public void setNavigationHandler(String navigationHandlerName) {
+ if (navigationHandler == null) {
+ navigationHandler = new ArrayList<String>();
+ }
+ String clean = navigationHandlerName.replaceAll("[ \t\r\n]", "");
+ String[] navigationHandlerNames = clean.split(",");
+
+ for (int i = 0; i < navigationHandlerNames.length; i++) {
+ navigationHandler.add(navigationHandlerNames[i]);
+ }
+ }
+
+ /**
+ * Takes a comma delimited string of class names and stores the names in an
+ * <code>ArrayList</code>. The incoming <code>String</code> will be
+ * cleaned of any whitespace characters before the class names are stored.
+ *
+ * @param propertyResolverName
+ * A comma delimited string of class names
+ */
+ public void setPropertyResolver(String propertyResolverName) {
+ if (propertyResolver == null) {
+ propertyResolver = new ArrayList<String>();
+ }
+ String clean = propertyResolverName.replaceAll("[ \t\r\n]", "");
+ String[] propertyResolverNames = clean.split(",");
+
+ for (int i = 0; i < propertyResolverNames.length; i++) {
+ propertyResolver.add(propertyResolverNames[i]);
+ }
+ }
+
+ /**
+ * Takes a comma delimited string of class names and stores the names in an
+ * <code>ArrayList</code>. The incoming <code>String</code> will be
+ * cleaned of any whitespace characters before the class names are stored.
+ *
+ * @param stateManagerName
+ * A comma delimited string of class names
+ */
+ public void setStateManager(String stateManagerName) {
+ if (stateManager == null) {
+ stateManager = new ArrayList<String>();
+ }
+ String clean = stateManagerName.replaceAll("[ \t\r\n]", "");
+ String[] stateManagerNames = clean.split(",");
+
+ for (int i = 0; i < stateManagerNames.length; i++) {
+ stateManager.add(stateManagerNames[i]);
+ }
+ }
+
+ /**
+ * Takes a comma delimited string of class names and stores the names in an
+ * <code>ArrayList</code>. The incoming <code>String</code> will be
+ * cleaned of any whitespace characters before the class names are stored.
+ *
+ * @param variableResolverName
+ * A comma delimited string of class names
+ */
+ public void setVariableResolver(String variableResolverName) {
+ if (variableResolver == null) {
+ variableResolver = new ArrayList<String>();
+ }
+ String clean = variableResolverName.replaceAll("[ \t\r\n]", "");
+ String[] variableResolverNames = clean.split(",");
+
+ for (int i = 0; i < variableResolverNames.length; i++) {
+ variableResolver.add(variableResolverNames[i]);
+ }
+ }
+
+ /**
+ * Takes a comma delimited string of class names and stores the names in an
+ * <code>ArrayList</code>. The incoming <code>String</code> will be
+ * cleaned of any whitespace characters before the class names are stored.
+ *
+ * @param viewHandlerName
+ * A comma delimited string of class names
+ */
+ public void setViewHandler(String viewHandlerName) {
+ if (viewHandler == null) {
+ viewHandler = new ArrayList<String>();
+ }
+ String[] viewHandlerNames = viewHandlerName
+ .split(",^[ \t\r\n]+|[ \t\r\n]+$");
+
+ for (int i = 0; i < viewHandlerNames.length; i++) {
+ viewHandler.add(viewHandlerNames[i]);
+ }
+ }
+
+ /**
+ * Converts a locale string to <code>Locale</code> class. Accepts both '_'
+ * and '-' as separators for locale components.
+ *
+ * @param localeString
+ * string representation of a locale
+ * @return Locale instance, compatible with the string representation
+ */
+ private Locale toLocale(String localeString) {
+ if ((localeString == null) || (localeString.length() == 0)) {
+ Locale locale = Locale.getDefault();
+ if (log.isWarnEnabled())
+ log
+ .warn("Locale name in faces-config.xml null or empty,
setting locale to default locale : "
+ + locale.toString());
+ return locale;
+ }
+
+ int separatorCountry = localeString.indexOf('_');
+ char separator;
+ if (separatorCountry >= 0) {
+ separator = '_';
+ } else {
+ separatorCountry = localeString.indexOf('-');
+ separator = '-';
+ }
+
+ String language, country, variant;
+ if (separatorCountry < 0) {
+ language = localeString;
+ country = variant = "";
+ } else {
+ language = localeString.substring(0, separatorCountry);
+
+ int separatorVariant = localeString.indexOf(separator,
+ separatorCountry + 1);
+ if (separatorVariant < 0) {
+ country = localeString.substring(separatorCountry + 1);
+ variant = "";
+ } else {
+ country = localeString.substring(separatorCountry + 1,
+ separatorVariant);
+ variant = localeString.substring(separatorVariant + 1);
+ }
+ }
+
+ return new Locale(language, country, variant);
}
}
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/StrutsVariableResolver.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/StrutsVariableResolver.java?view=diff&rev=440278&r1=440277&r2=440278
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/StrutsVariableResolver.java
(original)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/jsf/StrutsVariableResolver.java
Mon Sep 4 23:40:29 2006
@@ -21,50 +21,59 @@
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
+import com.opensymphony.xwork2.util.OgnlValueStack;
import com.opensymphony.xwork2.ActionContext;
/**
- * Adds the current Action instance to the variable lookups. All other requests
- * delegate to underlying resolver.
+ * Will return a reference to the current action if the action name matches the
+ * requested variable name. Otherwise it will attempt to resolve the name from
+ * the value stack. Otherwise it will delegate to the original jsf resolver.
*/
public class StrutsVariableResolver extends VariableResolver {
- /** The original <code>VariableResolver</code> passed to our
constructor. */
- private VariableResolver original = null;
+ /** The original <code>VariableResolver</code> passed to our constructor.
*/
+ private VariableResolver original = null;
- /** The variable name of our Struts action */
- private static final String STRUTS_VARIABLE_NAME = "action";
+ /** The variable name of our Struts action */
+ private static final String STRUTS_VARIABLE_NAME = "action";
- /**
- * Constructor
- *
- * @param original
- * Original resolver to delegate to.
- */
- public StrutsVariableResolver(VariableResolver original) {
-
- this.original = original;
-
- }
-
- /**
- * <p>
- * Resolve variable names known to this resolver; otherwise, delegate
to the
- * original resolver passed to our constructor.
- * </p>
- *
- * @param name
- * Variable name to be resolved
- */
- public Object resolveVariable(FacesContext context, String name)
- throws EvaluationException {
-
- if (STRUTS_VARIABLE_NAME.equals(name)) {
- return
ActionContext.getContext().getActionInvocation().getAction();
- } else {
- return original.resolveVariable(context, name);
- }
+ /**
+ * Constructor
+ *
+ * @param original
+ * Original resolver to delegate to.
+ */
+ public StrutsVariableResolver(VariableResolver original) {
+
+ this.original = original;
+
+ }
+
+ /**
+ * <p>
+ * Will return a reference to the current action if the action name matches
+ * the requested variable name. Otherwise it will attempt to resolve the
+ * name from the value stack. Otherwise it will delegate to the original
jsf
+ * resolver.
+ * </p>
+ *
+ * @param name
+ * Variable name to be resolved
+ */
+ public Object resolveVariable(FacesContext context, String name)
+ throws EvaluationException {
+
+ if (STRUTS_VARIABLE_NAME.equals(name)) {
+ return
ActionContext.getContext().getActionInvocation().getAction();
+ }
+
+ Object obj =
ActionContext.getContext().getValueStack().findValue(name);
+ if (obj != null) {
+ return obj;
+ } else {
+ return original.resolveVariable(context, name);
+ }
- }
+ }
}
Modified: struts/struts2/trunk/core/src/main/resources/struts-default.xml
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/struts-default.xml?view=diff&rev=440278&r1=440277&r2=440278
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/struts-default.xml (original)
+++ struts/struts2/trunk/core/src/main/resources/struts-default.xml Mon Sep 4
23:40:29 2006
@@ -187,7 +187,10 @@
<!-- Sample JSF stack, can be combined with other stacks easily -->
<interceptor-stack name="jsfStack">
- <interceptor-ref name="jsfSetup" />
+ <interceptor-ref name="jsfSetup">
+ <param
name="variableResolver">org.apache.struts2.jsf.StrutsVariableResolver</param>
+ <param
name="navigationHandler">org.apache.struts2.jsf.StrutsNavigationHandler</param>
+ </interceptor-ref>
<interceptor-ref name="jsfRestore" />
<interceptor-ref name="jsfApply" />
<interceptor-ref name="jsfValidate" />