You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by mr...@apache.org on 2006/05/21 06:13:55 UTC

svn commit: r408129 - in /struts/action2/trunk: apps/showcase/ apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/ apps/showcase/src/main/webapp/WEB-INF/ apps/showcase/src/main/webapp/WEB-INF/classes/ apps/showcase/src/main/webapp/WEB-I...

Author: mrdon
Date: Sat May 20 21:13:53 2006
New Revision: 408129

URL: http://svn.apache.org/viewvc?rev=408129&view=rev
Log:
Merges JSF into Action 2, allowing JSF components and backing beans to
be able to be used along side regular saf2 actions.  Furthermore, the
familiar feel of an action-based framework is brought to JSF pages,
giving each page its own action and making that action available in the
component's expressions.  This commit also includes a new section in the
showcase, demonstrating the JSF support.

WW-1320

Added:
    struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/
    struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/Employee.java
    struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeAction.java
    struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeDao.java
    struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/IndexAction.java
    struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/classes/xwork-jsf.xml
    struts/action2/trunk/apps/showcase/src/main/webapp/jsf/
    struts/action2/trunk/apps/showcase/src/main/webapp/jsf/employee.jsp
    struts/action2/trunk/apps/showcase/src/main/webapp/jsf/index.jsp
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/ApplyRequestValuesInterceptor.java
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesInterceptor.java
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesResult.java
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSetupInterceptor.java
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSupport.java
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/InvokeApplicationInterceptor.java
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/ProcessValidationsInterceptor.java
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/RestoreViewInterceptor.java
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/StrutsNavigationHandler.java
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/StrutsVariableResolver.java
    struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/UpdateModelValuesInterceptor.java
    struts/action2/trunk/core/src/main/resources/org/apache/struts/action2/jsf/
    struts/action2/trunk/core/src/main/resources/org/apache/struts/action2/jsf/package.html
Modified:
    struts/action2/trunk/apps/showcase/pom.xml
    struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/classes/xwork.xml
    struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
    struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/web.xml
    struts/action2/trunk/core/pom.xml
    struts/action2/trunk/core/src/main/resources/struts-default.xml

Modified: struts/action2/trunk/apps/showcase/pom.xml
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/pom.xml?rev=408129&r1=408128&r2=408129&view=diff
==============================================================================
--- struts/action2/trunk/apps/showcase/pom.xml (original)
+++ struts/action2/trunk/apps/showcase/pom.xml Sat May 20 21:13:53 2006
@@ -83,6 +83,17 @@
             <version>1.2.1</version>
             <scope>provided</scope>
         </dependency>
+		
+		<dependency>
+	     <groupId>myfaces</groupId>
+	     <artifactId>myfaces-impl</artifactId>
+	     <version>1.1.2</version>
+      </dependency>
+      <dependency>
+	     <groupId>myfaces</groupId>
+	     <artifactId>myfaces-api</artifactId>
+	     <version>1.1.2</version>
+	  </dependency>
  
     </dependencies>
     

Added: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/Employee.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/Employee.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/Employee.java (added)
+++ struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/Employee.java Sat May 20 21:13:53 2006
@@ -0,0 +1,37 @@
+package org.apache.struts.action2.showcase.jsf;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class Employee {
+	private String name;
+	private int id;
+	private List skills;
+	
+	public Employee() {}
+	
+	public Employee(int id, String name, String[] skills) {
+		this.id = id;
+		this.name = name;
+		this.skills = Arrays.asList(skills);
+	}
+	
+	public int getId() {
+		return id;
+	}
+	public void setId(int id) {
+		this.id = id;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public List getSkills() {
+		return skills;
+	}
+	public void setSkills(List skills) {
+		this.skills = skills;
+	}
+}

Added: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeAction.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeAction.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeAction.java (added)
+++ struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeAction.java Sat May 20 21:13:53 2006
@@ -0,0 +1,58 @@
+/*
+ * $Id: QuizAction.java 394498 2006-04-16 15:28:06Z 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.struts.action2.showcase.jsf;
+
+import java.util.List;
+
+import com.opensymphony.xwork.ActionSupport;
+
+public class EmployeeAction extends ActionSupport {
+	
+	private static final long serialVersionUID = 1L;
+
+	private Employee employee;
+	private int id;
+	
+	public EmployeeAction() {
+		employee = new Employee();
+	}
+	
+	public Employee getEmployee() {
+		return employee;
+	}
+	
+	public String[] getAllSkills() {
+		return EmployeeDao.getSkills();
+	}
+	
+	public void setId(int id) {
+		this.id = id;
+	}
+	
+    public String execute() {
+    	this.employee = EmployeeDao.getEmployee(id);
+    	return SUCCESS;
+    }
+    
+    public String save() {
+    	EmployeeDao.save(employee);
+    	return "index";
+    }
+    
+}
+

Added: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeDao.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeDao.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeDao.java (added)
+++ struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/EmployeeDao.java Sat May 20 21:13:53 2006
@@ -0,0 +1,37 @@
+package org.apache.struts.action2.showcase.jsf;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class EmployeeDao {
+	
+	private static String[] skills;
+	
+	private static List<Employee> employees;
+	
+	static {
+		employees = new ArrayList<Employee>();
+		employees.add(new Employee(0, "Tom Jones", new String[]{"Java", "PHP"}));
+		employees.add(new Employee(1, "Bart Simpson", new String[]{"PHP"}));
+		employees.add(new Employee(2, "Sofia Jones", new String[]{"Java"}));
+		
+		skills = new String[]{"Java", "PHP", "C#"};
+	}
+	
+	public static List<Employee> getEmployees() {
+		return employees;
+	}
+	
+	public static Employee getEmployee(int id) {
+		return employees.get(id);
+	}
+	
+	public static void save(Employee e) {
+		employees.set(e.getId(), e);
+	}
+	
+	public static String[] getSkills() {
+		return skills;
+	}
+}

Added: struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/IndexAction.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/IndexAction.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/IndexAction.java (added)
+++ struts/action2/trunk/apps/showcase/src/main/java/org/apache/struts/action2/showcase/jsf/IndexAction.java Sat May 20 21:13:53 2006
@@ -0,0 +1,43 @@
+/*
+ * $Id: QuizAction.java 394498 2006-04-16 15:28:06Z 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.struts.action2.showcase.jsf;
+
+import java.util.List;
+
+import com.opensymphony.xwork.ActionSupport;
+
+public class IndexAction extends ActionSupport {
+	
+	private static final long serialVersionUID = 1L;
+
+	private List loadedEmployees;
+	
+	public List getEmployees() {
+		System.out.println("getting employees:"+loadedEmployees);
+		return loadedEmployees;
+	}
+
+    public String execute() {
+    	System.out.println("executing");
+    	loadedEmployees = EmployeeDao.getEmployees();
+    	
+    	return SUCCESS;
+    }
+    
+}
+

Added: struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/classes/xwork-jsf.xml
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/classes/xwork-jsf.xml?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/classes/xwork-jsf.xml (added)
+++ struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/classes/xwork-jsf.xml Sat May 20 21:13:53 2006
@@ -0,0 +1,21 @@
+<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
+<xwork>
+    <include file="struts-default.xml"/>
+
+    <package name="jsf" extends="struts-default" namespace="/jsf">
+		
+        <action name="index" class="org.apache.struts.action2.showcase.jsf.IndexAction">
+            <interceptor-ref name="jsfStack"/>
+            <result name="success" type="jsf" />
+        </action>
+		
+		<action name="employee" class="org.apache.struts.action2.showcase.jsf.EmployeeAction">
+            <interceptor-ref name="basicStack"/>
+            <interceptor-ref name="jsfStack"/>
+            <result name="success" type="jsf" />
+			<result name="index" type="redirect-action">index</result>
+        </action>
+
+    </package>
+
+</xwork>

Modified: struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/classes/xwork.xml
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/classes/xwork.xml?rev=408129&r1=408128&r2=408129&view=diff
==============================================================================
--- struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/classes/xwork.xml (original)
+++ struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/classes/xwork.xml Sat May 20 21:13:53 2006
@@ -23,6 +23,8 @@
     <include file="xwork-person.xml" />
 
     <include file="xwork-wait.xml" />
+	
+	<include file="xwork-jsf.xml" />
 
     <include file="xwork-token.xml" />
     

Modified: struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp?rev=408129&r1=408128&r2=408129&view=diff
==============================================================================
--- struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp (original)
+++ struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp Sat May 20 21:13:53 2006
@@ -75,6 +75,7 @@
                     <li><a href="<saf:url value="/wait/index.jsp"/>">Execute & Wait</a></li>
                     <li><a href="<saf:url value="/token/index.jsp"/>">Token</a></li>
                     <li><a href="<saf:url value="/filedownload/index.jsp"/>">File Download</a></li>
+                    <li><a href="<saf:url action="index" namespace="/jsf"/>">JSF</a></li>
                     <li class="last"><a href="<saf:url value="/help.jsp"/>">Help</a></li>
                 </ul>
             </div>

Modified: struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/web.xml?rev=408129&r1=408128&r2=408129&view=diff
==============================================================================
--- struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/web.xml (original)
+++ struts/action2/trunk/apps/showcase/src/main/webapp/WEB-INF/web.xml Sat May 20 21:13:53 2006
@@ -4,6 +4,7 @@
 
     <display-name>WebWork Showcase Application</display-name>
 
+	
     <filter>
         <filter-name>action2-cleanup</filter-name>
         <filter-class>org.apache.struts.action2.dispatcher.ActionContextCleanUp</filter-class>
@@ -18,6 +19,8 @@
         <filter-name>sitemesh</filter-name>
         <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
     </filter>
+	
+	
 
     <filter-mapping>
         <filter-name>action2-cleanup</filter-name>
@@ -38,8 +41,13 @@
     <listener>
         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
     </listener>
-
-
+	
+	<listener>
+    <listener-class>
+      org.apache.myfaces.webapp.StartupServletContextListener
+    </listener-class>
+  </listener>
+	
     <!-- SNIPPET START: dwr -->
 
     <servlet>
@@ -50,6 +58,19 @@
             <param-value>true</param-value>
         </init-param>
     </servlet>
+	
+	<!-- JavaServer Faces Servlet Configuration, not used directly -->
+  	<servlet>
+    	<servlet-name>faces</servlet-name>
+	    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+    	<load-on-startup>1</load-on-startup>
+  	</servlet>
+
+  	<!-- JavaServer Faces Servlet Mapping, not called directly -->
+  	<servlet-mapping>
+    	<servlet-name>faces</servlet-name>
+    	<url-pattern>*.action</url-pattern>
+  	</servlet-mapping>
 
     <servlet-mapping>
         <servlet-name>dwr</servlet-name>

Added: struts/action2/trunk/apps/showcase/src/main/webapp/jsf/employee.jsp
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/webapp/jsf/employee.jsp?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/apps/showcase/src/main/webapp/jsf/employee.jsp (added)
+++ struts/action2/trunk/apps/showcase/src/main/webapp/jsf/employee.jsp Sat May 20 21:13:53 2006
@@ -0,0 +1,61 @@
+<%--
+
+ 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.
+
+ $Id: welcome.jsp 371852 2006-01-24 07:25:10Z craigmcc $
+
+--%>
+
+<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
+<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
+
+<f:view>
+
+<html>
+
+  <head>
+    <title>JSF Integration Examples</title>
+  </head>
+
+  <body>
+  
+  	<h2>Modify Employee</h2>
+  	
+  	<h:form>
+  		<h:inputHidden value="#{action.employee.id}" />
+  		<h:panelGrid columns="2">
+  			<h:outputText value="ID:" />
+  			<h:outputText value="#{action.employee.id}" />
+  			<h:outputText value="Name:" />
+  			<h:inputText size="30" value="#{action.employee.name}" />
+  			<h:outputText value="Skills:" />
+  			<h:selectManyCheckbox value="#{action.employee.skills}">
+  				<f:selectItem itemValue="Java" itemLabel="Java" />
+				<f:selectItem itemValue="PHP" itemLabel="PHP" />
+				<f:selectItem itemValue="Ruby" itemLabel="Ruby" />
+  			</h:selectManyCheckbox>	
+  		</h:panelGrid>
+  		
+  		<h:commandButton value="Submit" action="#{action.save}" />
+  		<br /><br />
+  		<h:outputLink value="index.action">
+  			<h:outputText value="Back" />
+  		</h:outputLink>
+  	</h:form>
+  </body>
+
+</html>
+
+</f:view>

Added: struts/action2/trunk/apps/showcase/src/main/webapp/jsf/index.jsp
URL: http://svn.apache.org/viewvc/struts/action2/trunk/apps/showcase/src/main/webapp/jsf/index.jsp?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/apps/showcase/src/main/webapp/jsf/index.jsp (added)
+++ struts/action2/trunk/apps/showcase/src/main/webapp/jsf/index.jsp Sat May 20 21:13:53 2006
@@ -0,0 +1,68 @@
+<%--
+
+ 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.
+
+ $Id: welcome.jsp 371852 2006-01-24 07:25:10Z craigmcc $
+
+--%>
+
+<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
+<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
+
+<f:view>
+
+<html>
+
+  <head>
+    <title>JSF Integration Examples</title>
+  </head>
+
+  <body>
+  	<h2>JSF Integration Examples</h2>
+  	<p>
+  	The following pages show how Struts Action 2 and JSF components can work together,
+  	each doing what they do best.
+  	</p>
+  	
+  	<h3>Employee List</h3>
+  	
+  	<h:dataTable value="#{action.employees}" var="e">
+  		<h:column>
+  			<f:facet name="header">
+  				<h:outputText value="ID" />
+  			</f:facet>
+  			<h:outputLink value="employee.action">
+  				<f:param name="id" value="#{e.id}" />
+  				<h:outputText value="#{e.id}" />
+  			</h:outputLink>	
+  		</h:column>
+		<h:column>
+  			<f:facet name="header">
+  				<h:outputText value="Name" />
+  			</f:facet>
+  			<h:outputText value="#{e.name}" />
+  		</h:column>
+  		<h:column>
+  			<f:facet name="header">
+  				<h:outputText value="Skills" />
+  			</f:facet>
+  			<h:outputText value="#{e.skills}" />
+  		</h:column>
+  	</h:dataTable>	
+  </body>
+
+</html>
+
+</f:view>

Modified: struts/action2/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/pom.xml?rev=408129&r1=408128&r2=408129&view=diff
==============================================================================
--- struts/action2/trunk/core/pom.xml (original)
+++ struts/action2/trunk/core/pom.xml Sat May 20 21:13:53 2006
@@ -258,6 +258,13 @@
             <version>1.2.6</version>
             <scope>test</scope>
         </dependency>
+        
+        <dependency>
+	     <groupId>myfaces</groupId>
+	     <artifactId>myfaces-jsf-api</artifactId>
+	     <version>1.0.9</version>
+        <scope>provided</scope>
+	  </dependency>
 
         <!-- Test dependencies -->
         <dependency>

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/ApplyRequestValuesInterceptor.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/ApplyRequestValuesInterceptor.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/ApplyRequestValuesInterceptor.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/ApplyRequestValuesInterceptor.java Sat May 20 21:13:53 2006
@@ -0,0 +1,70 @@
+/*
+ * $Id: TokenInterceptor.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.struts.action2.jsf;
+
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+
+/**
+ * Applies the request values to the component tree
+ */
+public class ApplyRequestValuesInterceptor extends FacesInterceptor {
+
+	private static final long serialVersionUID = -1471180154211835323L;
+
+	/**
+	 * Apply Request Values (JSF.2.2.2)
+	 * 
+	 * @param viewId The view id
+	 * @param facesContext The faces context
+	 * @return true, if response is complete
+	 */
+	protected boolean executePhase(String viewId, FacesContext facesContext)
+			throws FacesException {
+		boolean skipFurtherProcessing = false;
+		if (log.isTraceEnabled())
+			log.trace("entering applyRequestValues");
+
+		informPhaseListenersBefore(facesContext, PhaseId.APPLY_REQUEST_VALUES);
+
+		if (isResponseComplete(facesContext, "applyRequestValues", true)) {
+			// have to return right away
+			return true;
+		}
+		if (shouldRenderResponse(facesContext, "applyRequestValues", true)) {
+			skipFurtherProcessing = true;
+		}
+
+		facesContext.getViewRoot().processDecodes(facesContext);
+
+		informPhaseListenersAfter(facesContext, PhaseId.APPLY_REQUEST_VALUES);
+
+		if (isResponseComplete(facesContext, "applyRequestValues", false)
+				|| shouldRenderResponse(facesContext, "applyRequestValues",
+						false)) {
+			// since this phase is completed we don't need to return right away
+			// even if the response is completed
+			skipFurtherProcessing = true;
+		}
+
+		if (!skipFurtherProcessing && log.isTraceEnabled())
+			log.trace("exiting applyRequestValues");
+		return skipFurtherProcessing;
+	}
+}

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesInterceptor.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesInterceptor.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesInterceptor.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesInterceptor.java Sat May 20 21:13:53 2006
@@ -0,0 +1,90 @@
+/*
+ * $Id: TokenInterceptor.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.struts.action2.jsf;
+
+import javax.faces.context.FacesContext;
+
+import com.opensymphony.xwork.ActionInvocation;
+import com.opensymphony.xwork.interceptor.Interceptor;
+
+/**
+ * Translates JSF phases into individual interceptors, and adapts their expected
+ * workflow to Action 2
+ */
+public class FacesInterceptor extends FacesSupport implements Interceptor {
+
+	private static final long serialVersionUID = -5418255964277566516L;
+
+	/**
+	 * Not used
+	 */
+	public void init() {
+	}
+
+	/**
+	 * Adapts the phase workflow to Action 2
+	 * 
+	 * @param invocation
+	 *            The action invocation
+	 * @return The string result code
+	 */
+	public String intercept(ActionInvocation invocation) throws Exception {
+
+		FacesContext context = FacesContext.getCurrentInstance();
+
+		if (context.getRenderResponse()) {
+			return invocation.invoke();
+		} else {
+			String viewId = invocation.getProxy().getNamespace() + '/'
+					+ invocation.getProxy().getActionName();
+			executePhase(viewId, context);
+
+			if (context.getResponseComplete()) {
+				// Abort the chain as the result is done
+				return null;
+			} else {
+				if (invocation.getResultCode() != null) {
+					return invocation.getResultCode();
+				} else {
+					return invocation.invoke();
+				}
+			}
+		}
+	}
+
+	/**
+	 * Executes the specific phase. The phase id is constructed as a composite
+	 * of the namespace and action name.
+	 * 
+	 * @param viewId
+	 *            The view id
+	 * @param facesContext
+	 *            The current faces context
+	 * @return True if the next phases should be skipped
+	 */
+	protected boolean executePhase(String viewId, FacesContext facesContext) {
+		return false;
+	}
+
+	/**
+	 * Not used
+	 */
+	public void destroy() {
+	}
+
+}
\ No newline at end of file

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesResult.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesResult.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesResult.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesResult.java Sat May 20 21:13:53 2006
@@ -0,0 +1,85 @@
+/*
+ * $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.struts.action2.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;
+
+import com.opensymphony.xwork.ActionInvocation;
+import com.opensymphony.xwork.Result;
+
+/**
+ * Executes the JSF render phase
+ */
+public class FacesResult extends FacesSupport implements Result {
+
+	private static final long serialVersionUID = -3548970638740937804L;
+
+	/**
+	 * Executes the result
+	 */
+	public void execute(ActionInvocation invocation) throws Exception {
+		render(FacesContext.getCurrentInstance());
+	}
+
+	/**
+	 * 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);
+		// 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);
+		}
+
+		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");
+	}
+
+}

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSetupInterceptor.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSetupInterceptor.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSetupInterceptor.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSetupInterceptor.java Sat May 20 21:13:53 2006
@@ -0,0 +1,110 @@
+/*
+ * $Id: TokenInterceptor.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.struts.action2.jsf;
+
+import javax.faces.FactoryFinder;
+import javax.faces.application.Application;
+import javax.faces.application.ApplicationFactory;
+import javax.faces.context.FacesContext;
+import javax.faces.context.FacesContextFactory;
+import javax.faces.lifecycle.Lifecycle;
+import javax.faces.lifecycle.LifecycleFactory;
+
+import org.apache.struts.action2.ServletActionContext;
+
+import com.opensymphony.xwork.ActionInvocation;
+import com.opensymphony.xwork.interceptor.Interceptor;
+
+/**
+ * Initializes the JSF context for this request
+ */
+public class FacesSetupInterceptor extends FacesSupport implements Interceptor {
+
+	private static final long serialVersionUID = -621512342655103941L;
+
+	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() {
+		facesContextFactory = (FacesContextFactory) FactoryFinder
+				.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
+		// 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());
+		}
+		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 {
+		FacesContext facesContext = facesContextFactory.getFacesContext(
+				ServletActionContext.getServletContext(), ServletActionContext
+						.getRequest(), ServletActionContext.getResponse(),
+				lifecycle);
+
+		setLifecycle(lifecycle);
+
+		try {
+			return invocation.invoke();
+		} finally {
+			facesContext.release();
+		}
+	}
+
+	/**
+	 * Cleans up the lifecycle and factories
+	 */
+	public void destroy() {
+		facesContextFactory = null;
+		lifecycle = null;
+	}
+}

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSupport.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSupport.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSupport.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/FacesSupport.java Sat May 20 21:13:53 2006
@@ -0,0 +1,164 @@
+/*
+ * $Id: TokenInterceptor.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.struts.action2.jsf;
+
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import javax.faces.lifecycle.Lifecycle;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.opensymphony.xwork.ActionContext;
+
+/**
+ * Provides common lifecycle phase methods needed by interceptors and results.
+ */
+public class FacesSupport {
+
+	private static final String LIFECYCLE_KEY = "lifecycle";
+
+	/** Log instance for each class */
+	protected Log log;
+
+	/** Initializes log instance for the instance object */
+	protected FacesSupport() {
+		log = LogFactory.getLog(getClass());
+	}
+
+	/**
+	 * Gets the shared lifecycle for this request
+	 * 
+	 * @return The lifecycle
+	 */
+	private Lifecycle getLifecycle() {
+		return (Lifecycle) ActionContext.getContext().get(LIFECYCLE_KEY);
+	}
+
+	/**
+	 * Sets the lifecycle for this request
+	 * 
+	 * @param lifecycle
+	 *            The lifecycle
+	 */
+	protected void setLifecycle(Lifecycle lifecycle) {
+		ActionContext.getContext().put(LIFECYCLE_KEY, lifecycle);
+	}
+
+	/**
+	 * Informs phase listeners before a phase is executed
+	 * 
+	 * @param facesContext
+	 *            The current faces context
+	 * @param phaseId
+	 *            The phase id about to be executed
+	 */
+	protected void informPhaseListenersBefore(FacesContext facesContext,
+			PhaseId phaseId) {
+		Lifecycle lifecycle = getLifecycle();
+		PhaseListener[] phaseListeners = lifecycle.getPhaseListeners();
+		for (int i = 0; i < phaseListeners.length; i++) {
+			PhaseListener phaseListener = phaseListeners[i];
+			int listenerPhaseId = phaseListener.getPhaseId().getOrdinal();
+			if (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal()
+					|| listenerPhaseId == phaseId.getOrdinal()) {
+				phaseListener.beforePhase(new PhaseEvent(FacesContext
+						.getCurrentInstance(), phaseId, lifecycle));
+			}
+		}
+
+	}
+
+	/**
+	 * Informs phase listeners after a phase is executed
+	 * 
+	 * @param facesContext
+	 *            The current faces context
+	 * @param phaseId
+	 *            The phase id that was executed
+	 */
+	protected void informPhaseListenersAfter(FacesContext facesContext,
+			PhaseId phaseId) {
+		Lifecycle lifecycle = getLifecycle();
+		PhaseListener[] phaseListeners = lifecycle.getPhaseListeners();
+		for (int i = 0; i < phaseListeners.length; i++) {
+			PhaseListener phaseListener = phaseListeners[i];
+			int listenerPhaseId = phaseListener.getPhaseId().getOrdinal();
+			if (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal()
+					|| listenerPhaseId == phaseId.getOrdinal()) {
+				phaseListener.afterPhase(new PhaseEvent(FacesContext
+						.getCurrentInstance(), phaseId, lifecycle));
+			}
+		}
+
+	}
+
+	/**
+	 * Checks to see if the response has been completed. Mainly used for better
+	 * debugging messages.
+	 * 
+	 * @param facesContext
+	 *            The current faces context
+	 * @param phase
+	 *            The phase id in execution
+	 * @param before
+	 *            Whether the phase has been executed or not
+	 * @return True if the response is complete
+	 */
+	protected boolean isResponseComplete(FacesContext facesContext,
+			String phase, boolean before) {
+		boolean flag = false;
+		if (facesContext.getResponseComplete()) {
+			if (log.isDebugEnabled())
+				log
+						.debug("exiting from lifecycle.execute in "
+								+ phase
+								+ " because getResponseComplete is true from one of the "
+								+ (before ? "before" : "after") + " listeners");
+			flag = true;
+		}
+		return flag;
+	}
+
+	/**
+	 * Checks to see the render phase should be executed next. Mainly used for
+	 * better debugging messages.
+	 * 
+	 * @param facesContext
+	 *            The current faces context
+	 * @param phase
+	 *            The phase id in execution
+	 * @param before
+	 *            Whether the phase has been executed or not
+	 * @return True if the response is complete
+	 */
+	protected boolean shouldRenderResponse(FacesContext facesContext,
+			String phase, boolean before) {
+		boolean flag = false;
+		if (facesContext.getRenderResponse()) {
+			if (log.isDebugEnabled())
+				log.debug("exiting from lifecycle.execute in " + phase
+						+ " because getRenderResponse is true from one of the "
+						+ (before ? "before" : "after") + " listeners");
+			flag = true;
+		}
+		return flag;
+	}
+}

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/InvokeApplicationInterceptor.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/InvokeApplicationInterceptor.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/InvokeApplicationInterceptor.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/InvokeApplicationInterceptor.java Sat May 20 21:13:53 2006
@@ -0,0 +1,73 @@
+/*
+ * $Id: TokenInterceptor.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.struts.action2.jsf;
+
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+
+/**
+ * Invokes the application
+ */
+public class InvokeApplicationInterceptor extends FacesInterceptor {
+
+	private static final long serialVersionUID = -7388153356410171208L;
+
+	/**
+	 * Invoke Application (JSF.2.2.5)
+	 * 
+	 * @param viewId
+	 *            The view id
+	 * @param facesContext
+	 *            The faces context
+	 * @return true, if response is complete
+	 */
+	protected boolean executePhase(String viewId, FacesContext facesContext)
+			throws FacesException {
+		boolean skipFurtherProcessing = false;
+		if (log.isTraceEnabled())
+			log.trace("entering invokeApplication");
+
+		informPhaseListenersBefore(facesContext, PhaseId.INVOKE_APPLICATION);
+
+		if (isResponseComplete(facesContext, "invokeApplication", true)) {
+			// have to return right away
+			return true;
+		}
+		if (shouldRenderResponse(facesContext, "invokeApplication", true)) {
+			skipFurtherProcessing = true;
+		}
+
+		facesContext.getViewRoot().processApplication(facesContext);
+
+		informPhaseListenersAfter(facesContext, PhaseId.INVOKE_APPLICATION);
+
+		if (isResponseComplete(facesContext, "invokeApplication", false)
+				|| shouldRenderResponse(facesContext, "invokeApplication",
+						false)) {
+			// since this phase is completed we don't need to return right away
+			// even if the response is completed
+			skipFurtherProcessing = true;
+		}
+
+		if (!skipFurtherProcessing && log.isTraceEnabled())
+			log.trace("exiting invokeApplication ");
+
+		return skipFurtherProcessing;
+	}
+}

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/ProcessValidationsInterceptor.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/ProcessValidationsInterceptor.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/ProcessValidationsInterceptor.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/ProcessValidationsInterceptor.java Sat May 20 21:13:53 2006
@@ -0,0 +1,72 @@
+/*
+ * $Id: TokenInterceptor.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.struts.action2.jsf;
+
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+
+/**
+ * Processes validations on the component tree
+ */
+public class ProcessValidationsInterceptor extends FacesInterceptor {
+
+	private static final long serialVersionUID = 8785236570688278147L;
+
+	/**
+	 * Process Validations (JSF.2.2.3)
+	 * 
+	 * @param viewId
+	 *            The view id
+	 * @param facesContext
+	 *            The faces context
+	 * @return true, if response is complete
+	 */
+	protected boolean executePhase(String viewId, FacesContext facesContext)
+			throws FacesException {
+		boolean skipFurtherProcessing = false;
+		if (log.isTraceEnabled())
+			log.trace("entering processValidations");
+
+		informPhaseListenersBefore(facesContext, PhaseId.PROCESS_VALIDATIONS);
+
+		if (isResponseComplete(facesContext, "processValidations", true)) {
+			// have to return right away
+			return true;
+		}
+		if (shouldRenderResponse(facesContext, "processValidations", true)) {
+			skipFurtherProcessing = true;
+		}
+
+		facesContext.getViewRoot().processValidators(facesContext);
+
+		informPhaseListenersAfter(facesContext, PhaseId.PROCESS_VALIDATIONS);
+
+		if (isResponseComplete(facesContext, "processValidations", false)
+				|| shouldRenderResponse(facesContext, "processValidations",
+						false)) {
+			// since this phase is completed we don't need to return right away
+			// even if the response is completed
+			skipFurtherProcessing = true;
+		}
+
+		if (!skipFurtherProcessing && log.isTraceEnabled())
+			log.trace("exiting processValidations");
+		return skipFurtherProcessing;
+	}
+}

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/RestoreViewInterceptor.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/RestoreViewInterceptor.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/RestoreViewInterceptor.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/RestoreViewInterceptor.java Sat May 20 21:13:53 2006
@@ -0,0 +1,221 @@
+/*
+ * $Id: TokenInterceptor.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.struts.action2.jsf;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+
+import javax.faces.FacesException;
+import javax.faces.application.Application;
+import javax.faces.application.ViewHandler;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.el.ValueBinding;
+import javax.faces.event.PhaseId;
+
+/**
+ * Restores the view or component tree
+ */
+public class RestoreViewInterceptor extends FacesInterceptor {
+
+	private static final long serialVersionUID = -1500785113037140668L;
+
+	/**
+	 * Restore View (JSF.2.2.1)
+	 * 
+	 * @param viewId
+	 *            The view id
+	 * @param facesContext
+	 *            The faces context
+	 * @return true, if immediate rendering should occur
+	 */
+	protected boolean executePhase(String viewId, FacesContext facesContext) {
+		boolean skipFurtherProcessing = false;
+		if (log.isTraceEnabled())
+			log.trace("entering restoreView");
+
+		informPhaseListenersBefore(facesContext, PhaseId.RESTORE_VIEW);
+
+		if (isResponseComplete(facesContext, "restoreView", true)) {
+			// have to skips this phase
+			return true;
+		}
+		if (shouldRenderResponse(facesContext, "restoreView", true)) {
+			skipFurtherProcessing = true;
+		}
+
+		ExternalContext externalContext = facesContext.getExternalContext();
+		String defaultSuffix = externalContext
+				.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
+		String suffix = defaultSuffix != null ? defaultSuffix
+				: ViewHandler.DEFAULT_SUFFIX;
+		if (viewId != null) {
+			viewId += suffix;
+		}
+
+		if (viewId == null) {
+			if (!externalContext.getRequestServletPath().endsWith("/")) {
+				try {
+					externalContext.redirect(externalContext
+							.getRequestServletPath()
+							+ "/");
+					facesContext.responseComplete();
+					return true;
+				} catch (IOException e) {
+					throw new FacesException("redirect failed", e);
+				}
+			}
+		}
+
+		Application application = facesContext.getApplication();
+		ViewHandler viewHandler = application.getViewHandler();
+
+		// boolean viewCreated = false;
+		UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewId);
+		if (viewRoot == null) {
+			viewRoot = viewHandler.createView(facesContext, viewId);
+			viewRoot.setViewId(viewId);
+			facesContext.renderResponse();
+			// viewCreated = true;
+		}
+
+		facesContext.setViewRoot(viewRoot);
+
+		/*
+		 * This section has been disabled because it causes some bug. Be careful
+		 * if you need to re-enable it. Furthermore, for an unknown reason, it
+		 * seems that by default it is executed (i.e. log.isTraceEnabled() is
+		 * true). Bug example : This traceView causes DebugUtil.printComponent
+		 * to print all the attributes of the view components. And if you have a
+		 * data table within an aliasBean, this causes the data table to
+		 * initialize it's value attribute while the alias isn't set. So, the
+		 * value initializes with an UIData.EMPTY_DATA_MODEL, and not with the
+		 * aliased one. But as it's initialized, it will not try to get the
+		 * value from the ValueBinding next time it needs to. I expect this to
+		 * cause more similar bugs. TODO : Completely remove or be SURE by
+		 * default it's not executed, and it has no more side-effects.
+		 * 
+		 * if (log.isTraceEnabled()) { //Note: DebugUtils Logger must also be in
+		 * trace level DebugUtils.traceView(viewCreated ? "Newly created view" :
+		 * "Restored view"); }
+		 */
+
+		if (facesContext.getExternalContext().getRequestParameterMap()
+				.isEmpty()) {
+			// no POST or query parameters --> set render response flag
+			facesContext.renderResponse();
+		}
+
+		recursivelyHandleComponentReferencesAndSetValid(facesContext, viewRoot);
+
+		informPhaseListenersAfter(facesContext, PhaseId.RESTORE_VIEW);
+
+		if (isResponseComplete(facesContext, "restoreView", false)
+				|| shouldRenderResponse(facesContext, "restoreView", false)) {
+			// since this phase is completed we don't need to return right away
+			// even if the response is completed
+			skipFurtherProcessing = true;
+		}
+
+		if (!skipFurtherProcessing && log.isTraceEnabled())
+			log.trace("exiting restoreView ");
+		return skipFurtherProcessing;
+	}
+
+	/**
+	 * Walk the component tree, executing any component-bindings to reattach
+	 * components to their backing beans. Also, any UIInput component is marked
+	 * as Valid.
+	 * <p>
+	 * Note that this method effectively breaks encapsulation; instead of asking
+	 * each component to update itself and its children, this method just
+	 * reaches into each component. That makes it impossible for any component
+	 * to customise its behaviour at this point.
+	 * <p>
+	 * This has been filed as an issue against the spec. Until this issue is
+	 * resolved, we'll add a new marker-interface for components to allow them
+	 * to define their interest in handling children bindings themselves.
+	 */
+	protected void recursivelyHandleComponentReferencesAndSetValid(
+			FacesContext facesContext, UIComponent parent) {
+		recursivelyHandleComponentReferencesAndSetValid(facesContext, parent,
+				false);
+	}
+
+	protected void recursivelyHandleComponentReferencesAndSetValid(
+			FacesContext facesContext, UIComponent parent, boolean forceHandle) {
+		Method handleBindingsMethod = getBindingMethod(parent);
+
+		if (handleBindingsMethod != null && !forceHandle) {
+			try {
+				handleBindingsMethod.invoke(parent, new Object[] {});
+			} catch (Throwable th) {
+				log.error(
+						"Exception while invoking handleBindings on component with client-id:"
+								+ parent.getClientId(facesContext), th);
+			}
+		} else {
+			for (Iterator it = parent.getFacetsAndChildren(); it.hasNext();) {
+				UIComponent component = (UIComponent) it.next();
+
+				ValueBinding binding = component.getValueBinding("binding"); // TODO:
+																				// constant
+				if (binding != null && !binding.isReadOnly(facesContext)) {
+					binding.setValue(facesContext, component);
+				}
+
+				if (component instanceof UIInput) {
+					((UIInput) component).setValid(true);
+				}
+
+				recursivelyHandleComponentReferencesAndSetValid(facesContext,
+						component);
+			}
+		}
+	}
+
+	/**
+	 * This is all a hack to work around a spec-bug which will be fixed in
+	 * JSF2.0
+	 * 
+	 * @param parent
+	 * @return true if this component is bindingAware (e.g. aliasBean)
+	 */
+	private static Method getBindingMethod(UIComponent parent) {
+		Class[] clazzes = parent.getClass().getInterfaces();
+
+		for (int i = 0; i < clazzes.length; i++) {
+			Class clazz = clazzes[i];
+
+			if (clazz.getName().indexOf("BindingAware") != -1) {
+				try {
+					return parent.getClass().getMethod("handleBindings",
+							new Class[] {});
+				} catch (NoSuchMethodException e) {
+					// return
+				}
+			}
+		}
+
+		return null;
+	}
+}

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/StrutsNavigationHandler.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/StrutsNavigationHandler.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/StrutsNavigationHandler.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/StrutsNavigationHandler.java Sat May 20 21:13:53 2006
@@ -0,0 +1,46 @@
+/*
+ * $Id: TokenInterceptor.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.struts.action2.jsf;
+
+import javax.faces.application.NavigationHandler;
+import javax.faces.context.FacesContext;
+
+import com.opensymphony.xwork.ActionContext;
+
+/**
+ * Overrides the JFS navigation by delegating the result to handling by the core
+ * result code lookup and execution.
+ */
+public class StrutsNavigationHandler extends NavigationHandler {
+
+	/**
+	 * Stores any outcomes as the result code
+	 * 
+	 * @param facesContext The faces context
+	 * @param fromAction The action we are coming from
+	 * @param outcome The String return code
+	 */
+	@Override
+	public void handleNavigation(FacesContext facesContext, String fromAction, String outcome) {
+		ActionContext ctx = ActionContext.getContext();
+		if (outcome != null) {
+			ctx.getActionInvocation().setResultCode(outcome);
+		}
+	}
+
+}

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/StrutsVariableResolver.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/StrutsVariableResolver.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/StrutsVariableResolver.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/StrutsVariableResolver.java Sat May 20 21:13:53 2006
@@ -0,0 +1,70 @@
+/*
+ * $Id: TokenInterceptor.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.struts.action2.jsf;
+
+import javax.faces.context.FacesContext;
+import javax.faces.el.EvaluationException;
+import javax.faces.el.VariableResolver;
+
+import com.opensymphony.xwork.ActionContext;
+
+/**
+ * Adds the current Action instance to the variable lookups. All other requests
+ * delegate to underlying resolver.
+ */
+public class StrutsVariableResolver extends VariableResolver {
+
+	/** 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";
+
+	/**
+	 * 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);
+		}
+
+	}
+
+}

Added: struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/UpdateModelValuesInterceptor.java
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/UpdateModelValuesInterceptor.java?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/UpdateModelValuesInterceptor.java (added)
+++ struts/action2/trunk/core/src/main/java/org/apache/struts/action2/jsf/UpdateModelValuesInterceptor.java Sat May 20 21:13:53 2006
@@ -0,0 +1,70 @@
+/*
+ * $Id: TokenInterceptor.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.struts.action2.jsf;
+
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+
+/**
+ * Updates the model values from the component tree
+ */
+public class UpdateModelValuesInterceptor extends FacesInterceptor {
+	
+	private static final long serialVersionUID = 4011504235094251077L;
+
+	/**
+     * Update Model Values (JSF.2.2.4)
+     * 
+     * @param viewId The view id
+     * @param facesContext The faces context
+     * @return true, if response is complete
+     */
+	protected boolean executePhase(String viewId, FacesContext facesContext) throws FacesException
+    {
+	    boolean skipFurtherProcessing = false;
+        if (log.isTraceEnabled()) log.trace("entering updateModelValues");
+
+        informPhaseListenersBefore(facesContext, PhaseId.UPDATE_MODEL_VALUES);
+
+        if(isResponseComplete(facesContext, "updateModelValues", true))
+        {
+        		// have to return right away
+        		return true;
+        }
+        if(shouldRenderResponse(facesContext, "updateModelValues", true))
+        {
+        		skipFurtherProcessing = true;
+        }
+
+        facesContext.getViewRoot().processUpdates(facesContext);
+
+        informPhaseListenersAfter(facesContext, PhaseId.UPDATE_MODEL_VALUES);
+
+		if (isResponseComplete(facesContext, "updateModelValues", false)
+				|| shouldRenderResponse(facesContext, "updateModelValues", false))
+        {
+        		// since this phase is completed we don't need to return right away even if the response is completed
+        		skipFurtherProcessing = true;
+        }
+
+        if (!skipFurtherProcessing && log.isTraceEnabled()) log.trace("exiting updateModelValues");
+
+        return skipFurtherProcessing;
+    }
+}

Added: struts/action2/trunk/core/src/main/resources/org/apache/struts/action2/jsf/package.html
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/resources/org/apache/struts/action2/jsf/package.html?rev=408129&view=auto
==============================================================================
--- struts/action2/trunk/core/src/main/resources/org/apache/struts/action2/jsf/package.html (added)
+++ struts/action2/trunk/core/src/main/resources/org/apache/struts/action2/jsf/package.html Sat May 20 21:13:53 2006
@@ -0,0 +1,9 @@
+<body>
+Integrates the JSF library into the Struts Action Framework.  The overall approach
+	splits the JSF lifecycle into an Interceptor stack and Result, delegating
+	navigation and general controller functions to Struts.
+<p>
+	Most of this code was borrowed from MyFaces, and as such, will need to be synchronized 
+	occassionally with the original code.
+</p>
+</body>

Modified: struts/action2/trunk/core/src/main/resources/struts-default.xml
URL: http://svn.apache.org/viewvc/struts/action2/trunk/core/src/main/resources/struts-default.xml?rev=408129&r1=408128&r2=408129&view=diff
==============================================================================
--- struts/action2/trunk/core/src/main/resources/struts-default.xml (original)
+++ struts/action2/trunk/core/src/main/resources/struts-default.xml Sat May 20 21:13:53 2006
@@ -13,6 +13,7 @@
             <result-type name="velocity" class="org.apache.struts.action2.dispatcher.VelocityResult"/>
             <result-type name="xslt" class="org.apache.struts.action2.views.xslt.XSLTResult"/>
             <result-type name="plaintext" class="org.apache.struts.action2.dispatcher.PlainTextResult" />
+			<result-type name="jsf" class="org.apache.struts.action2.jsf.FacesResult" />
             
             <!-- third party integration -->
             <result-type name="jasper" class="org.apache.struts.action2.views.jasperreports.JasperReportsResult"/>
@@ -44,6 +45,14 @@
             <interceptor name="token-session" class="org.apache.struts.action2.interceptor.TokenSessionStoreInterceptor"/>
             <interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
             <interceptor name="workflow" class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor"/>
+			
+			<!-- JSF interceptors, one per lifecycle phase -->
+			<interceptor class="org.apache.struts.action2.jsf.FacesSetupInterceptor" name="jsfSetup" />
+			<interceptor class="org.apache.struts.action2.jsf.RestoreViewInterceptor" name="jsfRestore" />
+			<interceptor class="org.apache.struts.action2.jsf.ApplyRequestValuesInterceptor" name="jsfApply" />
+			<interceptor class="org.apache.struts.action2.jsf.ProcessValidationsInterceptor" name="jsfValidate" />
+			<interceptor class="org.apache.struts.action2.jsf.UpdateModelValuesInterceptor" name="jsfUpdate" />
+			<interceptor class="org.apache.struts.action2.jsf.InvokeApplicationInterceptor" name="jsfInvoke" />
 
             <!-- Basic stack -->
             <interceptor-stack name="basicStack">
@@ -176,6 +185,16 @@
                 <interceptor-ref name="execAndWait">
                     <param name="excludeMethods">input,back,cancel</param>
                 </interceptor-ref>
+            </interceptor-stack>
+			
+			<!-- Sample JSF stack, can be combined with other stacks easily -->
+			<interceptor-stack name="jsfStack">
+                <interceptor-ref name="jsfSetup" />
+				<interceptor-ref name="jsfRestore" />
+				<interceptor-ref name="jsfApply" />
+				<interceptor-ref name="jsfValidate" />
+				<interceptor-ref name="jsfUpdate" />
+				<interceptor-ref name="jsfInvoke" />
             </interceptor-stack>
         </interceptors>