[ajax4jsf-svn-commits] JBoss Ajax4JSF SVN: r274 - in trunk: gwtjsf and 6 other directories.

ajax4jsf-svn-commits at lists.jboss.org ajax4jsf-svn-commits at lists.jboss.org
Fri Jun 22 03:53:56 EDT 2007


Author: RobJellinghaus
Date: 2007-06-22 03:53:56 -0400 (Fri, 22 Jun 2007)
New Revision: 274

Added:
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerServiceHelper.java
Removed:
   trunk/build.xml
   trunk/gwtjsf/src/main/resources/META-INF/gwt/gwt.js
Modified:
   trunk/gwtjsf/pom.xml
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/client/ComponentEntryPoint.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/client/ui/JSFImage.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtCallListener.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtEvent.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListener.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerHandler.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerHelper.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerMethodHelper.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtPhaseListener.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/PageRenderer.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/WidgetRenderer.java
   trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/server/GwtFacesServlet.java
   trunk/gwtjsf/src/main/resources/META-INF/faces-config.xml
   trunk/pom.xml
Log:
This commit integrates Rob Jellinghaus' patches to the gwtjsf library, 
making it compatible with GWT 1.4, enabling direct RPC access from gwtjsf
components to RPC server interfaces (no longer limited to GwtFacesService),
and providing full support for Seam.  See http://unrealities.com/seamgwt
for fuller documentation and explanation.  Also see this thread:
http://jboss.com/index.html?module=bb&op=viewtopic&t=111314


Deleted: trunk/build.xml
===================================================================
--- trunk/build.xml	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/build.xml	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,264 +0,0 @@
-<project name="ajax4jsf" default="distribute">
-	<property name="commonLibs.dir" value="${basedir}/commonLibs"></property>
-	
-	<property name="distrib.dir" value="${basedir}/distribution"/>
-	<property name="work.dir" value="${basedir}/build"/>
-	
-	<property name="src.root.dir" value="${basedir}/src"></property>
-	
-	<property name="test.src.dir" value="${src.root.dir}/testCase"></property>
-	<property name="framework.src.dir" value="${src.root.dir}/framework"></property>
-	<property name="framework.java.src.dir" value="${framework.src.dir}/java"></property>
-	<property name="framework.js.src.dir" value="${framework.src.dir}/JavaScript"></property>
-	<property name="framework.generate.src.dir" value="${framework.src.dir}/generate"></property>
-	<property name="framework.build.dir" value="${work.dir}/framework"></property>
-
-	<property name="cdk.src.dir" value="${src.root.dir}/cdk"></property>
-	<property name="cdk.build.dir" value="${work.dir}/cdk"></property>
-
-	<property name="doc.root.dir" value="${distrib.dir}/docs"></property>
-	<property name="tlddoc.dir" value="${doc.root.dir}/tldDoc"></property>
-	<property name="javadoc.dir" value="${doc.root.dir}/javaAPI"></property>
-
-	<property name="tlddoc.jar" value="${commonLibs.dir}/tlddoc.jar"></property>
-	
-	<property name="framework-distribution-name" value="ajax4jsf"></property>
-	<property name="cdk-distribution-name" value="ajax4jsf-cdk" />
-	
-	<property name="generated-source.dir" value="${work.dir}/gen-src"></property>
-	
-	<fileset id="commonLibs" dir="${commonLibs.dir}">
-		<include name="*.jar"/>
-	</fileset>
-	
-	<path id="class-path">
-		<fileset refid="commonLibs"></fileset>
-	</path>
-
-	<target name="prepare">
-		<mkdir dir="${distrib.dir}"/>
-		<mkdir dir="${work.dir}"/>
-	</target>
-	
-	<target name="generate-framework" depends="compile-framework,compile-cdk">
-		<ant antfile="${framework.generate.src.dir}/build.xml" inheritall="true" dir="${basedir}" target="xml-merge">
-		</ant>
-	</target>
-
-
-
-	<target name="prepare-framework">
-		<mkdir dir="${framework.build.dir}" />
-	</target>
-
-	<target name="prepare-cdk">
-		<mkdir dir="${cdk.build.dir}" />
-	</target>
-
-	
-	<target name="compile-framework" depends="prepare-framework">
-		<javac 
-			destdir="${framework.build.dir}"
-			compiler="javac1.4" 
-			source="1.4" 
-			target="1.4" 
-			debug="true" 
-            failonerror="false"         
-			debuglevel="lines,vars,source">
-			<classpath refid="class-path"></classpath>
-			<src path="${framework.src.dir}"></src>
-		</javac>
-		<copy todir="${framework.build.dir}">
-			<fileset dir="${framework.java.src.dir}">
-				<include name="**/*.*"/>
-				<exclude name="**/*.java"/>
-				<exclude name="META-INF/*faces-config.xml"/>
-			</fileset>
-		</copy>
-	</target>
-
-	<target name="compile-cdk" depends="prepare-cdk">
-		<javac 
-			destdir="${cdk.build.dir}"
-			compiler="javac1.4" 
-			source="1.4" 
-			target="1.4" 
-			debug="true" 
-			debuglevel="lines,vars,source">
-				<classpath refid="class-path"></classpath>
-			<src path="${cdk.src.dir}"></src>
-		</javac>
-		<copy todir="${cdk.build.dir}/META-INF">
-			<fileset dir="${cdk.src.dir}/META-INF">
-				<include name="**/*.*"/>
-			</fileset>				
-		</copy>		
-	</target>
-	
-	<target name="compile-framework-phase2" depends="generate-framework">
-		<javac 
-			destdir="${framework.build.dir}"
-			compiler="javac1.4" 
-			source="1.4" 
-			target="1.4" 
-			debug="true" 
-			debuglevel="lines,vars,source">
-			<classpath>
-				<path>
-				<path refid="class-path"></path>
-				<pathelement path="${framework.build.dir}"/>
-				</path>
-			</classpath>
-			<src path="${generated-source.dir}"></src>
-		</javac>
-		<copy todir="${framework.build.dir}">
-			<fileset dir="${generated-source.dir}">
-				<include name="**/*.*"/>
-				<exclude name="**/*.java"/>
-				<exclude name="META-INF/*-faces-config.xml"/>
-			</fileset>
-		</copy>
-	</target>
-
-	
-	<target name="assemble-javascripts" depends="prepare-framework">
-		<ant antfile="${framework.js.src.dir}/build.xml" dir="${framework.js.src.dir}">
-			<property name="target-dir" value="${framework.build.dir}"></property>
-		</ant>
-	</target>
-	
-	<target name="build-framework" depends="compile-framework,assemble-javascripts,compile-framework-phase2">
-	</target>
-
-	<target name="build-cdk" depends="compile-cdk">
-	</target>
-	
-	<target name="prepare-distribution-dir">
-		<mkdir dir="${distrib.dir}/lib"/>
-	</target>
-	
-	<target name="package-framework" depends="build-framework, prepare-distribution-dir">
-		<jar destfile="${distrib.dir}/lib/${framework-distribution-name}.jar">
-			<fileset dir="${framework.build.dir}">
-				<include name="**/*.*"/>
-			</fileset>
-		</jar>
-	</target>
-	
-	<target name="package-cdk" depends="prepare-distribution-dir,build-cdk">
-		<jar destfile="${distrib.dir}/lib/${cdk-distribution-name}.jar">
-			<fileset dir="${cdk.build.dir}">
-				<include name="**/*.*"/>
-			</fileset>
-		</jar>
-	</target>
-
-					<target name="prepare-docs">
-		<mkdir dir="${doc.root.dir}"/>
-	</target>
-	
-	<target name="docs" depends="prepare-docs, javadoc, tlddoc, copy-doc">
-		
-	</target>
-	
-	<target name="copy-doc" depends="prepare-docs">
-		<copy todir="${doc.root.dir}" failonerror="false">
-			<fileset dir="${basedir}/doc">
-				<include name="**/*"/>
-			</fileset>
-		</copy>
-	</target>
-	
-	<target name="javadoc">
-		<mkdir dir="${javadoc.dir}"/>
-		<javadoc packagenames="org.*" destdir="${javadoc.dir}">
-			<sourcepath>
-				<pathelement path="${framework.java.src.dir}"/>
-			</sourcepath>
-			<classpath refid="class-path"></classpath>
-		</javadoc>
-	</target>
-	
-	<target name="tlddoc">
-		<mkdir dir="${tlddoc.dir}"/>
-		<echo message="${tlddoc.jar}"></echo>
-		<apply executable="java" parallel="true" verbose="true">
-			<!-- dir="${tlddoc.dir}">-->
-			<arg line="-jar ${tlddoc.jar}"/>
-			<arg line="-doctitle 'AJAX4JSF'"/>
-			<!--arg line="-xslt ${tlddocxsl.dir}"/-->
-			<arg line="-d ${tlddoc.dir}"/>
-			<fileset dir="${framework.build.dir}/META-INF" includes="**.tld"/>
-		</apply>
-	</target>
-	
-	<target name="copy-dependencies" depends="prepare-distribution-dir">
-		<copy todir="${distrib.dir}/lib">
-			<fileset dir="${commonLibs.dir}">
-				<include name="oscache*.jar"/>
-			</fileset>
-		</copy>
-	</target>
-	
-	<target name="copy-src">
-		<mkdir dir="${distrib.dir}/src"/>
-		<copy todir="${distrib.dir}/src">
-			<fileset dir="${framework.src.dir}">
-				<include name="**/*"/>
-			</fileset>
-		</copy>
-	</target>
-	
-	<target name="copy-demo">
-		<mkdir dir="${distrib.dir}/demo"/>
-		<copy todir="${distrib.dir}/demo" failonerror="false">
-			<fileset dir="${basedir}/demo">
-				<include name="**/*"/>
-			</fileset>
-		</copy>
-	</target>
-	
-	<target name="copy-txt">
-		<copy todir="${distrib.dir}">
-			<fileset dir="${basedir}">
-				<include name="*.txt"/>
-				<include name="*.TXT"/>
-			</fileset>
-		</copy>
-	</target>
-	
-	<target name="build-test-framework">
-		<javac 
-			destdir="${framework.build.dir}"
-			compiler="javac1.4" 
-			source="1.4" 
-			target="1.4" 
-			debug="true" 
-			debuglevel="lines,vars,source">
-			<classpath refid="class-path"></classpath>
-			<src path="${test.src.dir}"></src>
-		</javac>
-		<copy todir="${framework.build.dir}">
-			<fileset dir="${test.src.dir}">
-				<include name="**/*.*"/>
-				<exclude name="**/*.java"/>
-				<exclude name="META-INF/*"/>
-				<exclude name="WEB-INF/*"/>
-			</fileset>
-		</copy>
-	</target>
-	
-	<target name="distribute" depends="clean,build-framework,package-framework, copy-dependencies, docs, copy-src, copy-txt, copy-demo, package-cdk">
-		<!--delete dir="${work.dir}"></delete-->
-		<delete file="${basedir}/velocity.log" failonerror="false" verbose="true"></delete>
-	</target>
-	
-	<target name="clean">
-		<delete dir="${work.dir}"></delete>
-		<delete includeemptydirs="true" failonerror="false">
-			<fileset dir="${distrib.dir}">
-				<include name="**/*"/>
-			</fileset>
-		</delete>
-	</target>
-</project>

Modified: trunk/gwtjsf/pom.xml
===================================================================
--- trunk/gwtjsf/pom.xml	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/pom.xml	2007-06-22 07:53:56 UTC (rev 274)
@@ -3,14 +3,75 @@
 	<parent>
 		<artifactId>master</artifactId>
 		<groupId>org.ajax4jsf</groupId>
-		<version>1.1.1-SNAPSHOT</version>
+		<version>1.1.2-SNAPSHOT</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>org.ajax4jsf</groupId>
 	<artifactId>gwtjsf</artifactId>
 	<name>Google web toolkit and JSF integration library</name>
 	<url>https://ajax4jsf.dev.java.net</url>
-	<build>
+	<properties>
+		<jsfVersion>1.2</jsfVersion>
+	</properties>
+
+
+<!-- valiant, but failed, attempt to make GWTShell run under Maven.
+see http://groups.google.com/group/gwt-maven/browse_thread/thread/09885f643c7b4d67/# for painful details. 
+- RobJ 20070619 -->
+
+<!--
+    <profiles>
+        <profile>
+            <id>darwin</id>
+            <activation>
+            <os>
+                <family>mac</family>
+            </os>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>com.google.gwt</groupId>
+                    <artifactId>gwt-dev-mac</artifactId>
+                    <version>1.4.10</version>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>linux</id>
+            <activation>
+            <os>
+                <family>unix</family>
+            </os>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>com.google.gwt</groupId>
+                    <artifactId>gwt-dev-linux</artifactId>
+                    <version>1.4.10</version>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>windows</id>
+            <activation>
+            <os>
+                <family>windows</family>
+            </os>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>com.google.gwt</groupId>
+                    <artifactId>gwt-dev-linux</artifactId>
+                    <version>1.4.10</version>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles> 
+    
+-->	
+	
+    <build>
+
 		<plugins>
 			<plugin>
 				<artifactId>maven-source-plugin</artifactId>
@@ -23,10 +84,12 @@
 					</execution>
 				</executions>
 			</plugin>
-
 		</plugins>
+		
 	</build>
+
 	<dependencies>
+
 		<dependency>
 			<groupId>junit</groupId>
 			<artifactId>junit</artifactId>
@@ -43,13 +106,14 @@
 			<artifactId>jsf-facelets</artifactId>
 			<version>1.1.11</version>
 		</dependency>
+		
 		<dependency>
 			<groupId>javax.servlet</groupId>
 			<artifactId>servlet-api</artifactId>
 			<version>2.5</version>
 		</dependency>
 		<dependency>
-			<groupId>javax.servlet</groupId>
+			<groupId>javax.servlet.jsp</groupId>
 			<artifactId>jsp-api</artifactId>
 			<version>2.1</version>
 		</dependency>
@@ -63,20 +127,38 @@
 			<artifactId>jsf-impl</artifactId>
 			<version>1.2_03</version>
 		</dependency>
+		
 		<dependency>
 			<groupId>javax.el</groupId>
 			<artifactId>el-api</artifactId>
 			<version>1.0</version>
 		</dependency>
+		
 		<dependency>
 			<groupId>com.google.gwt</groupId>
 			<artifactId>gwt-servlet</artifactId>
-			<version>1.3.1</version>
+			<!-- updated to 1.4.10 - RobJ 20070615 -->
+			<version>1.4.10</version>
 		</dependency>
+		
 		<dependency>
 			<groupId>com.google.gwt</groupId>
 			<artifactId>gwt-user</artifactId>
-			<version>1.3.1</version>
+			<!-- set to scope=provided to prevent including in WAR, 
+				 as per http://gwt-maven.googlecode.com/svn/docs/maven-googlewebtoolkit2-plugin/index.html 
+			     - RobJ 20070615 -->
+			<scope>provided</scope>
+			<!-- updated to 1.4.10 - RobJ 20070615 -->
+			<version>1.4.10</version>
 		</dependency>
 	</dependencies>
+
+	<repositories>
+		<!-- add gwt-maven repository - RobJ 20070618 -->
+		<repository>
+			<id>gwt-maven</id>
+			<url>http://gwt-maven.googlecode.com/svn/trunk/mavenrepo/</url>
+		</repository>
+	</repositories>
+	
 </project>
\ No newline at end of file

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/client/ComponentEntryPoint.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/client/ComponentEntryPoint.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/client/ComponentEntryPoint.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,288 +1,352 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.client;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.rpc.ServiceDefTarget;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-/**
- * @author shura
- * 
- */
-public abstract class ComponentEntryPoint implements EntryPoint {
-
-	public static final String GWT_MODULE_NAME_PARAMETER = "x-gwtcallingmodule";
-	private static String viewState;
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see com.google.gwt.core.client.EntryPoint#onModuleLoad()
-	 */
-	public void onModuleLoad() {
-		// Init callback script
-		String jsFunction = "_create_" + GWT.getModuleName().replace('.', '_');
-		initJS(jsFunction);
-		List elements = findElementsForClass(RootPanel.getBodyElement(), GWT
-				.getModuleName());
-		Element viewStateField = DOM.getElementById("javax.faces.ViewState");
-		if (null != viewStateField) {
-			viewState = DOM.getAttribute(viewStateField, "value");
-		}
-		for (Iterator iter = elements.iterator(); iter.hasNext();) {
-			Element element = (Element) iter.next();
-			String id = DOM.getAttribute(element, "id");
-			// got viev state parameter
-			Widget widget = createWidget(id);
-			// RootPanel clear it content - widget can need use it.
-			RootPanel panel = RootPanel.get(id);
-			panel.add(widget);
-		}
-	}
-
-	/**
-	 * Get map of widget parameters. Default data will be stored in hidden span
-	 * element with id as id+":_data" by child elements - title attribute is
-	 * param name, enclosing text - value.
-	 * 
-	 * @param id -
-	 *            clientId of JSF component.
-	 * @return map of widget parameters.
-	 */
-	protected Map getWidgetParams(String id) {
-		// Parse parameters.
-		String dataId = id + ":_data";
-		Element dataElement = DOM.getElementById(dataId);
-		Map params = new HashMap();
-		if (null != dataElement) {
-			int childCount = DOM.getChildCount(dataElement);
-			fillParamsMap(dataElement, params, childCount);
-		}
-		return params;
-	}
-
-	/**
-	 * Fill parameters map by data from given element. If data element don't have child elements,
-	 * got content as text, else - put new map with content of recursive same method. 
-	 * @param dataElement
-	 * @param params
-	 * @param childCount
-	 */
-	private void fillParamsMap(Element dataElement, Map params, int childCount) {
-		for (int it = 0; it < childCount; it++) {
-			Element data = DOM.getChild(dataElement, it);
-			String key = DOM.getAttribute(data, "title");
-			if (null != key) {
-				int dataChildCount = DOM.getChildCount(data);
-				if (dataChildCount > 0) {
-					// Put data from child elements as new map
-					Map innerData = new HashMap(dataChildCount);
-					fillParamsMap(data,innerData,dataChildCount);
-					params.put(key,innerData);
-				} else {
-					// Simple text value
-					String innerText = DOM.getInnerText(data);
-					params.put(key, innerText);
-				}
-			}
-		}
-	}
-
-	public static native String getProperty(String name) /*-{
-	 return $wnd.__gwt_getMetaProperty(name);
-	 }-*/;
-
-	/**
-	 * Returns a List of Element objects that have the specified CSS class name.
-	 * 
-	 * @param element
-	 *            Element to start search from
-	 * @param className
-	 *            name of class to find
-	 * @return
-	 */
-	public static List findElementsForClass(Element element, String className) {
-		ArrayList result = new ArrayList();
-		recElementsForClass(result, element, className);
-		return result;
-	}
-
-	/**
-	 * Recursive search dom element and it's children for specified CSS class
-	 * name. helper method for {@link #findElementsForClass(Element, String)}
-	 * 
-	 * @param res
-	 * @param element
-	 * @param className
-	 */
-	private static void recElementsForClass(ArrayList res, Element element,
-			String className) {
-		if (isHaveClass(element, className)) {
-			res.add(element);
-		}
-
-		for (int i = 0; i < DOM.getChildCount(element); i++) {
-			Element child = DOM.getChild(element, i);
-			recElementsForClass(res, child, className);
-		}
-	}
-
-	/**
-	 * Check for dom element is have specified ctyle class.
-	 * 
-	 * @param element
-	 * @param className
-	 * @return
-	 */
-	public static boolean isHaveClass(Element element, String className) {
-		String c = DOM.getAttribute(element, "className");
-
-		if (c != null) {
-			String[] p = c.split(" ");
-
-			for (int x = 0; x < p.length; x++) {
-				if (p[x].equals(className)) {
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * Append content of given element to widget. Can be used to append content
-	 * of rendered facet or children elements to widget.
-	 * 
-	 * @param widget
-	 *            target widget
-	 * @param content
-	 *            element with content for append to widget
-	 */
-	public static void appendContent(Widget widget, Element content) {
-		Element element = widget.getElement();
-		int childCount = DOM.getChildCount(content);
-		for (int i = 0; i < childCount; i++) {
-			Element child = DOM.getChild(content, i);
-			DOM.appendChild(element, child);
-		}
-	}
-
-	/**
-	 * Setup service endpoint to same as page action URL with view state
-	 * parameter.
-	 * 
-	 * @param service
-	 */
-	public static void setupServiceEndpoint(ServiceDefTarget service) {
-		String endpoint = getEndpoint();
-		service.setServiceEntryPoint(endpoint);
-	}
-
-	/**
-	 * @return
-	 */
-	public static String getEndpoint() {
-		String endpoint = getProperty("action") + "?javax.faces.ViewState="
-				+ viewState + "&x-gwtcallingmodule="+GWT.getModuleName();		
-		return endpoint;
-	}
-
-	/**
-	 * Factory method for create and setup JSF service to perform RPC call on
-	 * component instance
-	 * 
-	 * @param clientId -
-	 *            identify target component
-	 * @return service stub instance
-	 */
-	public static GwtFacesServiceAsync createFacesService(String clientId) {
-		GwtFacesServiceAsync service = (GwtFacesServiceAsync) GWT
-				.create(GwtFacesService.class);
-		String endpoint = getEndpoint();
-		if (null != clientId) {
-			endpoint = endpoint + "&clientId=" + clientId;
-		}
-		((ServiceDefTarget) service).setServiceEntryPoint(endpoint);
-		return service;
-	}
-
-	/**
-	 * Implementation must owerride this method to crete concrete widget
-	 * 
-	 * @param id -
-	 *            clientId of JSF component.
-	 * @return
-	 */
-	protected abstract Widget createWidget(String id);
-
-	/**
-	 * Create widget from Java-script inline in page ( can be used for re-create
-	 * widgets in Ajax4jsf .
-	 * 
-	 * @param id -
-	 *            IDREF for base widget element.
-	 */
-	public final void appendWidget(String id) {
-		// got viev state parameter
-		Widget widget = createWidget(id);
-		// RootPanel clear it content - widget can need use it.
-		RootPanel panel = RootPanel.get(id);
-		panel.add(widget);
-	}
-
-	/**
-	 * create javaScript funtion for callback creation of widgets in page.
-	 * 
-	 * @param moduleName
-	 */
-	private native void initJS(String moduleName)/*-{
-	 $wnd[moduleName] = function(id){
-	 this. at org.ajax4jsf.gwt.client.ComponentEntryPoint::appendWidget(Ljava/lang/String;)(id);
-	 };
-	 }-*/;
-
-	/**
-	 * @return Returns the viewState.
-	 */
-	public static String getViewState() {
-		return viewState;
-	}
-
-	/**
-	 * @param viewState
-	 *            The viewState to set.
-	 */
-	public static void setViewState(String viewState) {
-		ComponentEntryPoint.viewState = viewState;
-	}
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.client;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.rpc.ServiceDefTarget;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Base class for G4JSF components.  Provides infrastructure for hooking module loading, integrating
+ * with JSF state management, handling widget parameters, et al.
+ *
+ * @author shura
+ * @author Rob Jellinghaus
+ */
+public abstract class ComponentEntryPoint implements EntryPoint {
+
+	public static final String GWT_MODULE_NAME_PARAMETER = "x-gwtcallingmodule";
+	private static String viewState;
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see com.google.gwt.core.client.EntryPoint#onModuleLoad()
+	 */
+	public void onModuleLoad() {
+		// Init callback script
+		String jsFunction = "_create_" + GWT.getModuleName().replace('.', '_');
+		initJS(jsFunction);
+		List elements = findElementsForClass(RootPanel.getBodyElement(), GWT
+				.getModuleName());
+		Element viewStateField = DOM.getElementById("javax.faces.ViewState");
+		if (null != viewStateField) {
+			viewState = DOM.getAttribute(viewStateField, "value");
+		}
+		for (Iterator iter = elements.iterator(); iter.hasNext();) {
+			Element element = (Element) iter.next();
+			String id = DOM.getAttribute(element, "id");
+			// got viev state parameter
+			Widget widget = createWidget(id);
+			// RootPanel clear it content - widget can need use it.
+			RootPanel panel = RootPanel.get(id);
+			panel.add(widget);
+		}
+	}
+
+	/**
+	 * Get map of widget parameters. Default data will be stored in hidden span
+	 * element with id as id+":_data" by child elements - title attribute is
+	 * param name, enclosing text - value.
+	 *
+	 * @param id -
+	 *            clientId of JSF component.
+	 * @return map of widget parameters.
+	 */
+	protected Map getWidgetParams(String id) {
+		// Parse parameters.
+		String dataId = id + ":_data";
+		Element dataElement = DOM.getElementById(dataId);
+		Map params = new HashMap();
+		if (null != dataElement) {
+			int childCount = DOM.getChildCount(dataElement);
+			fillParamsMap(dataElement, params, childCount);
+		}
+		return params;
+	}
+
+	/**
+	 * Fill parameters map by data from given element. If data element don't have child elements,
+	 * got content as text, else - put new map with content of recursive same method.
+	 * @param dataElement
+	 * @param params
+	 * @param childCount
+	 */
+	private void fillParamsMap(Element dataElement, Map params, int childCount) {
+		for (int it = 0; it < childCount; it++) {
+			Element data = DOM.getChild(dataElement, it);
+			String key = DOM.getAttribute(data, "title");
+			if (null != key) {
+				int dataChildCount = DOM.getChildCount(data);
+				if (dataChildCount > 0) {
+					// Put data from child elements as new map
+					Map innerData = new HashMap(dataChildCount);
+					fillParamsMap(data,innerData,dataChildCount);
+					params.put(key,innerData);
+				} else {
+					// Simple text value
+					String innerText = DOM.getInnerText(data);
+					params.put(key, innerText);
+				}
+			}
+		}
+	}
+
+    /**
+     * Private cached static map of meta gwt:property values, defined as
+     * (meta name="gwt:property" content="propName=value").
+     */
+    private static Map gwtMetaProperties = null;
+
+    /**
+     * Get a named meta property from the current root panel's head element.
+     * Statically cached for efficiency.  Whoops, what if there are different meta properties
+     * on each page?
+     */
+    public static String getMetaProperty(String propName) {
+        if (gwtMetaProperties == null) {
+            gwtMetaProperties = new HashMap();
+
+            Element bodyElement = RootPanel.getBodyElement();
+            // go up to the parent
+            Element htmlElement = DOM.getParent(bodyElement);
+            // iterate over meta children
+            Element headElement = DOM.getFirstChild(htmlElement);
+
+            int count = DOM.getChildCount(headElement);
+            for (int i = 0; i < count; i++) {
+                Element nextChild = DOM.getChild(headElement, i);
+                if ("meta".equalsIgnoreCase(getElementTagName(nextChild))) {
+                    String nameAttribute = DOM.getAttribute(nextChild, "name");
+                    if ("gwt:property".equals(nameAttribute)) {
+                        String contentAttribute = DOM.getAttribute(nextChild, "content");
+                        if (contentAttribute != null) {
+                            int eqPos = contentAttribute.indexOf("=");
+                            if (eqPos != -1) {
+                                String name = contentAttribute.substring(0, eqPos);
+                                gwtMetaProperties.put(name, contentAttribute.substring(eqPos + 1));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return (String)gwtMetaProperties.get(propName);
+    }
+
+    /**
+     * Get the tag name of an element.  I can't believe this isn't in the DOM class.
+     */
+    public static native String getElementTagName (Element element) /*-{
+        return element.tagName;
+    }-*/;
+
+    // this doesn't work anymore because document is the cached module document, not the gwt.js
+    // main document.
+        /*-{
+	 // made private in module init function....
+	 //return __gwt_getMetaProperty(name);
+
+      var metas = document.getElementsByTagName("meta");
+      for (var i = 0, n = metas.length; i < n; ++i) {
+        var meta = metas[i];
+        var name = meta.getAttribute("name");
+        if (name) {
+          if (name == "gwt:property") {
+            var content = meta.getAttribute("content");
+            if (content) {
+              var name = content, value = "";
+              var eq = content.indexOf("=");
+              if (eq != -1) {
+                name = content.substring(0, eq);
+                value = content.substring(eq+1);
+              }
+              if (propName == name) {
+                return value;
+              }
+            }
+          }
+        }
+      }
+      return null;
+	 }-*/;
+
+	/**
+	 * Returns a List of Element objects that have the specified CSS class name.
+	 *
+	 * @param element
+	 *            Element to start search from
+	 * @param className
+	 *            name of class to find
+	 */
+	public static List findElementsForClass(Element element, String className) {
+		ArrayList result = new ArrayList();
+		recElementsForClass(result, element, className);
+		return result;
+	}
+
+	/**
+	 * Recursive search dom element and it's children for specified CSS class
+	 * name. helper method for {@link #findElementsForClass(Element, String)}
+	 *
+	 * @param res
+	 * @param element
+	 * @param className
+	 */
+	private static void recElementsForClass(ArrayList res, Element element,
+			String className) {
+		if (isHaveClass(element, className)) {
+			res.add(element);
+		}
+
+		for (int i = 0; i < DOM.getChildCount(element); i++) {
+			Element child = DOM.getChild(element, i);
+			recElementsForClass(res, child, className);
+		}
+	}
+
+	/**
+	 * Check for dom element is have specified ctyle class.
+	 *
+	 * @param element
+	 * @param className
+	 */
+	public static boolean isHaveClass(Element element, String className) {
+		String c = DOM.getAttribute(element, "className");
+
+		if (c != null) {
+			String[] p = c.split(" ");
+
+			for (int x = 0; x < p.length; x++) {
+				if (p[x].equals(className)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Append content of given element to widget. Can be used to append content
+	 * of rendered facet or children elements to widget.
+	 *
+	 * @param widget
+	 *            target widget
+	 * @param content
+	 *            element with content for append to widget
+	 */
+	public static void appendContent(Widget widget, Element content) {
+		Element element = widget.getElement();
+		int childCount = DOM.getChildCount(content);
+		for (int i = 0; i < childCount; i++) {
+			Element child = DOM.getChild(content, i);
+			DOM.appendChild(element, child);
+		}
+	}
+
+	/**
+	 * Setup service endpoint to same as page action URL with view state
+	 * parameter.
+	 *
+	 * @param service
+	 */
+	public static void setupServiceEndpoint(ServiceDefTarget service) {
+		String endpoint = getEndpoint();
+		service.setServiceEntryPoint(endpoint);
+	}
+
+	/**
+     * Get service endpoint URL.  Include JSF viewState and GWT module name as URL parameters,
+     * to facilitate JSF dispatching logic in GwtFacesServlet.
+	 */
+	public static String getEndpoint() {
+        String action = getMetaProperty("action");
+        String endpoint = action + "?javax.faces.ViewState="
+				+ viewState + "&x-gwtcallingmodule="+GWT.getModuleName();
+		return endpoint;
+	}
+
+	/**
+	 * Factory method for create and setup JSF service to perform RPC call on
+	 * component instance
+	 *
+	 * @param clientId -
+	 *            identify target component
+	 * @return service stub instance
+	 */
+	public static GwtFacesServiceAsync createFacesService(String clientId) {
+		GwtFacesServiceAsync service = (GwtFacesServiceAsync) GWT
+				.create(GwtFacesService.class);
+		String endpoint = getEndpoint();
+		if (null != clientId) {
+			endpoint = endpoint + "&clientId=" + clientId;
+		}
+		((ServiceDefTarget) service).setServiceEntryPoint(endpoint);
+		return service;
+	}
+
+	/**
+	 * Implementation must owerride this method to create concrete widget.  Note that
+     * the id passed will be the specific id of this type of widget, so if multiple
+     * widgets are implemented in this module, the createWidget method in the
+     * EntryPoint subclass can dispatch on the particular id to instantiate one widget
+     * or the other.
+	 *
+	 * @param id -
+	 *            clientId of JSF component.
+	 */
+	protected abstract Widget createWidget(String id);
+
+	/**
+	 * Create widget from Java-script inline in page ( can be used for re-create
+	 * widgets in Ajax4jsf .
+	 * 
+	 * @param id -
+	 *            IDREF for base widget element.
+	 */
+	public final void appendWidget(String id) {
+		// got viev state parameter
+		Widget widget = createWidget(id);
+		// RootPanel clear it content - widget can need use it.
+		RootPanel panel = RootPanel.get(id);
+		panel.add(widget);
+	}
+
+	/**
+	 * create javaScript funtion for callback creation of widgets in page.
+	 * 
+	 * @param moduleName
+	 */
+	private native void initJS(String moduleName)/*-{
+	 $wnd[moduleName] = function(id){
+	 this. at org.ajax4jsf.gwt.client.ComponentEntryPoint::appendWidget(Ljava/lang/String;)(id);
+	 };
+	 }-*/;
+
+	/**
+	 * @return Returns the viewState.
+	 */
+	public static String getViewState() {
+		return viewState;
+	}
+
+	/**
+	 * @param viewState
+	 *            The viewState to set.
+	 */
+	public static void setViewState(String viewState) {
+		ComponentEntryPoint.viewState = viewState;
+	}
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/client/ui/JSFImage.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/client/ui/JSFImage.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/client/ui/JSFImage.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,90 +1,72 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.client.ui;
-
-import org.ajax4jsf.gwt.client.ComponentEntryPoint;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.Image;
-
-/**
- * Version of original {@link com.google.gwt.user.client.ui.Image} widget to load
- * images in packed to jar images from module public path. This image will work with
- * same relative url's in hosted mode and as packed component.
- * @author shura
- *
- */
-public class JSFImage extends Image {
-
-	/**
-	 * 
-	 */
-	public JSFImage() {
-		super();
-		// TODO Auto-generated constructor stub
-	}
-	  /**
-	   * Causes the browser to pre-fetch the image at a given URL.
-	   * 
-	   * @param url the URL of the image to be prefetched
-	   */
-	  public static void prefetch(String url) {
-			String base = ComponentEntryPoint.getProperty("base");
-			if(null != base){
-				url=base+GWT.getModuleName()+"/"+url;
-			}
-			Image.prefetch(url);
-	  }
-
-	/**
-	 * @param arg0
-	 */
-	public JSFImage(String arg0) {
-		super(arg0);
-		// TODO Auto-generated constructor stub
-	}
-
-	/* (non-Javadoc)
-	 * @see com.google.gwt.user.client.ui.Image#getUrl()
-	 */
-	public String getUrl() {
-		// TODO Auto-generated method stub
-		String url = super.getUrl();
-		String base = ComponentEntryPoint.getProperty("base");
-		if(null != base){
-			url = url.substring((base+GWT.getModuleName()+"/").length());
-		}
-		return url;
-	}
-
-	/* (non-Javadoc)
-	 * @see com.google.gwt.user.client.ui.Image#setUrl(java.lang.String)
-	 */
-	public void setUrl(String url) {
-		String base = ComponentEntryPoint.getProperty("base");
-		if(null != base){
-			url=base+GWT.getModuleName()+"/"+url;
-		}
-		super.setUrl(url);
-	}
-
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.client.ui;
+
+import org.ajax4jsf.gwt.client.ComponentEntryPoint;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.ui.Image;
+
+/**
+ * Version of original {@link com.google.gwt.user.client.ui.Image} widget to load
+ * images in packed to jar images from module public path. This image will work with
+ * same relative url's in hosted mode and as packed component.
+ * @author shura
+ *
+ */
+public class JSFImage extends Image {
+
+	/**
+	 * 
+	 */
+	public JSFImage() {
+		super();
+		// TODO Auto-generated constructor stub
+	}
+	  /**
+	   * Causes the browser to pre-fetch the image at a given URL.
+	   * 
+	   * @param url the URL of the image to be prefetched
+	   */
+	  public static void prefetch(String url) {
+			String base = ComponentEntryPoint.getMetaProperty("base");
+			if(null != base){
+				url=base+GWT.getModuleName()+"/"+url;
+			}
+			Image.prefetch(url);
+	  }
+
+	/**
+	 * @param arg0
+	 */
+	public JSFImage(String arg0) {
+		super(arg0);
+		// TODO Auto-generated constructor stub
+	}
+
+	/* (non-Javadoc)
+	 * @see com.google.gwt.user.client.ui.Image#getUrl()
+	 */
+	public String getUrl() {
+		// TODO Auto-generated method stub
+		String url = super.getUrl();
+		String base = ComponentEntryPoint.getMetaProperty("base");
+		if(null != base){
+			url = url.substring((base+GWT.getModuleName()+"/").length());
+		}
+		return url;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.google.gwt.user.client.ui.Image#setUrl(java.lang.String)
+	 */
+	public void setUrl(String url) {
+		String base = ComponentEntryPoint.getMetaProperty("base");
+		if(null != base){
+			url=base+GWT.getModuleName()+"/"+url;
+		}
+		super.setUrl(url);
+	}
+
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtCallListener.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtCallListener.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtCallListener.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,45 +1,23 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.jsf;
-
-import javax.faces.event.PhaseEvent;
-import javax.faces.event.PhaseId;
-import javax.faces.event.PhaseListener;
-
-import org.ajax4jsf.gwt.client.GwtFacesEvent;
-import org.ajax4jsf.gwt.client.GwtFacesResult;
-
-public abstract class GwtCallListener implements PhaseListener {
-
-	public void afterPhase(PhaseEvent event) {
-	}
-
-	public void beforePhase(PhaseEvent event) {
-	}
-	
-	public abstract GwtFacesResult processGwtEvent(GwtFacesEvent event);
-
-	public PhaseId getPhaseId() {
-		return PhaseId.INVOKE_APPLICATION;
-	}
-
-}
+package org.ajax4jsf.gwt.jsf;
+
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+
+import com.google.gwt.user.server.rpc.RPCRequest;
+
+public abstract class GwtCallListener implements PhaseListener {
+
+    public void afterPhase(PhaseEvent event) {
+    }
+
+    public void beforePhase(PhaseEvent event) {
+    }
+
+    public abstract String processRequest(RPCRequest call);
+
+    public PhaseId getPhaseId() {
+        return PhaseId.INVOKE_APPLICATION;
+    }
+
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtEvent.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtEvent.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtEvent.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,80 +1,63 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.jsf;
-
-import javax.faces.component.UIComponent;
-import javax.faces.event.FacesEvent;
-import javax.faces.event.FacesListener;
-
-import org.ajax4jsf.gwt.client.GwtFacesEvent;
-import org.ajax4jsf.gwt.client.GwtFacesResult;
-
-/**
- * @author shura
- *
- */
-public abstract class GwtEvent extends FacesEvent {
-	
-//	private GwtFacesEvent gwtEventData;
-	
-	/**
-	 * @param source
-	 */
-	public GwtEvent(UIComponent source) {
-		super(source);
-	}
-
-	/* (non-Javadoc)
-	 * @see javax.faces.event.FacesEvent#isAppropriateListener(javax.faces.event.FacesListener)
-	 */
-	public boolean isAppropriateListener(FacesListener listener) {
-		if (listener instanceof GwtListener) {
-			GwtListener gwtListener = (GwtListener) listener;
-			return gwtListener.isAcceptEvent(getGwtEventData());
-		}
-		return false;
-	}
-
-	/* (non-Javadoc)
-	 * @see javax.faces.event.FacesEvent#processListener(javax.faces.event.FacesListener)
-	 */
-	public void processListener(FacesListener listener) {
-		GwtListener gwtListener = (GwtListener) listener;
-		setCallbackParameter(gwtListener.processEvent(this.getGwtEventData()));
-	}
-
-	/**
-	 * @return Returns the callbackParameter.
-	 */
-	public abstract GwtFacesResult getCallbackParameter();
-
-	/**
-	 * @param callbackParameter The callbackParameter to set.
-	 */
-	public abstract void setCallbackParameter(GwtFacesResult callbackParam);
-
-	/**
-	 * @return Returns the gwtEventData.
-	 */
-	public abstract GwtFacesEvent getGwtEventData();
-
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.jsf;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.FacesListener;
+
+import com.google.gwt.user.server.rpc.RPCRequest;
+
+/**
+ * Abstract superclass of GWT events that route GWT calls through JSF.
+ * @author shura
+ */
+public abstract class GwtEvent extends FacesEvent {
+
+    /**
+     * @param source
+     */
+    public GwtEvent(UIComponent source) {
+        super(source);
+    }
+
+    /**
+     * Is the listener appropriate?
+     * @param listener
+     */
+    public boolean isAppropriateListener (FacesListener listener) {
+        if (listener instanceof GwtListener) {
+            GwtListener gwtListener = (GwtListener) listener;
+            return gwtListener.canHandleRequest(getRPCRequest());
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+	 * @see javax.faces.event.FacesEvent#processListener(javax.faces.event.FacesListener)
+	 */
+    public void processListener(FacesListener listener) {
+        GwtListener gwtListener = (GwtListener) listener;
+        setCallbackParameter(gwtListener.processRequest(this.getRPCRequest()));
+    }
+
+    /**
+     * Get the GWT serialized response payload.
+     * @return the response payload
+     */
+    public abstract String getResponsePayload();
+
+    /**
+     * Set the response payload.  Called by the handler when it invokes the GWT call on the
+     * proper component.
+     * @param responsePayload the payload to set
+     */
+    public abstract void setCallbackParameter(String responsePayload);
+
+    /**
+     * Get the call that's being routed.
+     */
+    public abstract RPCRequest getRPCRequest();
+
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListener.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListener.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListener.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,39 +1,27 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.jsf;
-
-import javax.faces.event.FacesListener;
-
-import org.ajax4jsf.gwt.client.GwtFacesEvent;
-import org.ajax4jsf.gwt.client.GwtFacesResult;
-
-/**
- * @author shura
- *
- */
-public interface GwtListener extends FacesListener {
-	
-	public boolean isAcceptEvent(GwtFacesEvent event);
-	
-	public GwtFacesResult processEvent(GwtFacesEvent event);
-	
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.jsf;
+
+import com.google.gwt.user.server.rpc.RPCRequest;
+
+import javax.faces.event.FacesListener;
+
+/**
+ * General listener for GWT event handling.  Restricted to only the original GWTFacesService interface.
+ * @author shura
+ */
+public interface GwtListener extends FacesListener {
+
+    /**
+     * Can this listener handle the given call?
+     */
+    public boolean canHandleRequest (RPCRequest request);
+
+    /**
+     * Process the given call.
+     * @return the encoded GWT response payload
+     */
+    public String processRequest(RPCRequest request);
+	
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerHandler.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerHandler.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerHandler.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,128 +1,168 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.jsf;
-
-import java.io.IOException;
-
-import javax.el.ELException;
-import javax.el.MethodExpression;
-import javax.el.ValueExpression;
-import javax.faces.FacesException;
-import javax.faces.component.UIComponent;
-
-import org.ajax4jsf.gwt.client.GwtFacesResult;
-
-import com.sun.facelets.FaceletContext;
-import com.sun.facelets.FaceletException;
-import com.sun.facelets.tag.TagAttribute;
-import com.sun.facelets.tag.TagAttributeException;
-import com.sun.facelets.tag.TagConfig;
-import com.sun.facelets.tag.TagException;
-import com.sun.facelets.tag.TagHandler;
-
-/**
- * @author shura
- *
- */
-public class GwtListenerHandler extends TagHandler {
-
-    private Class listenerType;
-    
-    private Class[] signature = GwtActionsRule.GWT_LISTENER_SIG; 
-
-    private final TagAttribute type;
-
-    private final TagAttribute binding;
-
-    private final TagAttribute method;
-
-    private final TagAttribute event;
-
-    private Class eventType;
-
-    public GwtListenerHandler(TagConfig config) {
-		super(config);
-        this.binding = this.getAttribute("binding");
-        this.method = this.getAttribute("method");
-        this.event = this.getAttribute("event");
-        this.type = this.getAttribute("type");
-        if (type != null) {
-            if (!type.isLiteral()) {
-                throw new TagAttributeException(this.tag, this.type, "Must be literal");
-            }
-            try {
-                this.listenerType = Class.forName(type.getValue());
-            } catch (Exception e) {
-                throw new TagAttributeException(this.tag, this.type, e);
-            }
-        }
-        if (event != null) {
-            if (!event.isLiteral()) {
-                throw new TagAttributeException(this.tag, this.event, "Must be literal");
-            }
-            try {
-                this.eventType = Class.forName(event.getValue());
-            	this.signature = new Class[]{this.eventType};
-            } catch (Exception e) {
-                throw new TagAttributeException(this.tag, this.event, e);
-            }
-        }
-	}
-
-	/* (non-Javadoc)
-	 * @see com.sun.facelets.FaceletHandler#apply(com.sun.facelets.FaceletContext, javax.faces.component.UIComponent)
-	 */
-	public void apply(FaceletContext ctx, UIComponent parent)
-			throws IOException, FacesException, FaceletException, ELException {
-        if (parent instanceof GwtSource) {
-            // only process if parent was just created
-            if (parent.getParent() == null) {
-                GwtSource src = (GwtSource) parent;
-                GwtListener listener = null;
-                ValueExpression ve = null;
-                if (this.binding != null) {
-                    ve = this.binding.getValueExpression(ctx,
-                            GwtListener.class);
-                    listener = new GwtListenerHelper(ve);
-                } else if (this.method != null) {
-					MethodExpression me = this.method.getMethodExpression(ctx,GwtFacesResult.class,signature);
-                    listener = new GwtListenerMethodHelper(me,eventType);
-				}
-                if (listener == null) {
-                    try {
-                        listener = (GwtListener) listenerType.newInstance();
-                    } catch (Exception e) {
-                        throw new TagAttributeException(this.tag, this.type, e.getCause());
-                    }
-                    if (ve != null) {
-                        ve.setValue(ctx, ve);
-                    }
-                }
-                src.addGwtListener(listener);
-            }
-        } else {
-            throw new TagException(this.tag,
-                    "Parent is not of type GwtSource, type is: " + parent);
-        }
-	}
-
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.jsf;
+
+import java.io.IOException;
+
+import javax.el.ELException;
+import javax.el.MethodExpression;
+import javax.el.ValueExpression;
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+
+import org.ajax4jsf.gwt.client.GwtFacesResult;
+
+import com.sun.facelets.FaceletContext;
+import com.sun.facelets.FaceletException;
+import com.sun.facelets.tag.TagAttribute;
+import com.sun.facelets.tag.TagAttributeException;
+import com.sun.facelets.tag.TagConfig;
+import com.sun.facelets.tag.TagException;
+import com.sun.facelets.tag.TagHandler;
+
+/**
+ * Parses the attributes of a gwt:gwtListener tag, and creates the appropriate type of helper components
+ * in the JSF component tree.
+ * <p/>
+ * There are several attributes that can be used with this tag:
+ * <ul>
+ * <li>binding - this is an EL value expression that specifies an object implementing GwtListener;
+ * this object will be invoked to handle the request</li>
+ * <li>method - this is an EL method expression that specifies an object and method that take a
+ * single GwtFacesEvent argument; the GWT class must use GwtFacesService to route an event to this
+ * 'event handler' method</li>
+ * <li>event - the specific class of GwtFacesEvent to be passed to the 'event handler' method;
+ * this attribute must be used with the method attribute</li>
+ * <li>serviceBean - this is an EL value expression that resolves to an object that implements a
+ * GWT service interface; the incoming RPC will be delegated to this object (if it is an RPC on that
+ * object's interface)</li>
+ * <li>type - if no other attributes are defined, this is the class name of a GwtListener class that
+ * will be instantiated (with its no-argument constructor) and used to handle the RPC</li>
+ * </ul>
+ * Note that the binding, method, and serviceBean attributes are exclusive; each gwtListener tag must
+ * have only one of those attributes.  Multiple gwtListener tags may be used to define multiple
+ * listeners.
+ *
+ * @author shura
+ * @author Rob Jellinghaus
+ */
+public class GwtListenerHandler extends TagHandler {
+
+    private Class listenerType;
+    
+    private Class[] signature = GwtActionsRule.GWT_LISTENER_SIG;
+
+    /**
+     * A string literal specifying the type of listener to construct (via no-argument constructor)
+     * if no other attributes are defined on this tag.
+     */
+    private final TagAttribute type;
+
+    /**
+     * An EL value expression that yields a GwtListener instance which should process the request.
+     */
+    private final TagAttribute binding;
+
+    /**
+     * An EL method expression which yields a method that should be passed an instance of
+     * GwtFacesEvent.
+     */
+    private final TagAttribute method;
+
+    /**
+     * The specific subclass of GwtFacesEvent that should be passed to a declared method.
+     */
+    private final TagAttribute event;
+
+    /**
+     * An EL value expression that yields an object which implements a service interface to be
+     * invoked directly by RPC.
+     */
+    private final TagAttribute serviceBean;
+
+    private Class eventType;
+
+    /**
+     * Construct a GwtListenerHandler from the given tag.
+     */
+    public GwtListenerHandler(TagConfig config) {
+		super(config);
+        this.binding = this.getAttribute("binding");
+        this.method = this.getAttribute("method");
+        this.event = this.getAttribute("event");
+        this.type = this.getAttribute("type");
+        this.serviceBean = this.getAttribute("serviceBean");
+        if (type != null) {
+            if (!type.isLiteral()) {
+                throw new TagAttributeException(this.tag, this.type, "Must be literal");
+            }
+            try {
+                this.listenerType = Class.forName(type.getValue());
+            } catch (Exception e) {
+                throw new TagAttributeException(this.tag, this.type, e);
+            }
+        }
+        if (event != null) {
+            if (!event.isLiteral()) {
+                throw new TagAttributeException(this.tag, this.event, "Must be literal");
+            }
+            try {
+                this.eventType = Class.forName(event.getValue());
+            	this.signature = new Class[]{this.eventType};
+            } catch (Exception e) {
+                throw new TagAttributeException(this.tag, this.event, e);
+            }
+        }
+        int numAttrs = (binding == null ? 0 : 1) +
+                (method == null ? 0 : 1) +
+                (serviceBean == null ? 0 : 1);
+        if (numAttrs > 1) {
+            throw new TagException(this.tag,
+                    "Must have only one of 'binding', 'method', 'serviceBean' attributes on single gwtListener; " +
+                            "use multiple gwtListeners instead");
+        }
+	}
+
+	/**
+	 * @see com.sun.facelets.FaceletHandler#apply(com.sun.facelets.FaceletContext, javax.faces.component.UIComponent)
+	 */
+	public void apply(FaceletContext ctx, UIComponent parent)
+			throws IOException, FacesException, FaceletException, ELException {
+        if (parent instanceof GwtSource) {
+            // only process if parent was just created
+            if (parent.getParent() == null) {
+                GwtSource src = (GwtSource) parent;
+                GwtListener listener = null;
+                ValueExpression ve = null;
+                if (this.binding != null) {
+                    ve = this.binding.getValueExpression(ctx,
+                            GwtListener.class);
+                    listener = new GwtListenerHelper(ve);
+                } else if (this.method != null) {
+					MethodExpression me = this.method.getMethodExpression(ctx,GwtFacesResult.class,signature);
+                    listener = new GwtListenerMethodHelper(me,eventType);
+				} else if (this.serviceBean != null) {
+                    // could be any kind of object... we're not particular... yet
+                    ve = this.serviceBean.getValueExpression(ctx, Object.class);
+                    listener = new GwtListenerServiceHelper(ve);
+                }
+                if (listener == null) {
+                    try {
+                        listener = (GwtListener) listenerType.newInstance();
+                    } catch (Exception e) {
+                        throw new TagAttributeException(this.tag, this.type, e.getCause());
+                    }
+                    if (ve != null) {
+                        ve.setValue(ctx, ve);
+                    }
+                }
+                src.addGwtListener(listener);
+            }
+        } else {
+            throw new TagException(this.tag,
+                    "Parent is not of type GwtSource, type is: " + parent);
+        }
+	}
+
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerHelper.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerHelper.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerHelper.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,133 +1,113 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.jsf;
-
-import java.io.Serializable;
-
-import javax.el.ELContext;
-import javax.el.MethodExpression;
-import javax.el.ValueExpression;
-import javax.faces.component.StateHolder;
-import javax.faces.component.UIComponentBase;
-import javax.faces.context.FacesContext;
-
-import org.ajax4jsf.gwt.client.GwtFacesEvent;
-import org.ajax4jsf.gwt.client.GwtFacesResult;
-
-/**
- * @author shura
- *
- */
-public class GwtListenerHelper implements GwtListener,StateHolder {
-	
-	
-	private ValueExpression _binding;
-	
-	
-	private boolean _transient = false;
-
-	
-	/**
-	 * 
-	 */
-	public GwtListenerHelper() {
-		super();
-		// TODO Auto-generated constructor stub
-	}
-
-	/**
-	 * @param binding
-	 */
-	public GwtListenerHelper(ValueExpression binding) {
-		super();
-		if (null == binding) {
-			throw new IllegalArgumentException("Binding expression for GwtListener helper must be not null");
-		}
-		_binding = binding;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.ajax4jsf.gwt.jsf.GwtListener#isAcceptEvent(org.ajax4jsf.gwt.client.GwtFacesEvent)
-	 */
-	public boolean isAcceptEvent(GwtFacesEvent event) {
-		ELContext context = FacesContext.getCurrentInstance().getELContext();
-			GwtListener handler = getHandler(context);
-			return handler.isAcceptEvent(event);
-	}
-
-	private GwtListener getHandler(ELContext context) {
-		return (GwtListener) _binding.getValue(context);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.ajax4jsf.gwt.jsf.GwtListener#processEvent(org.ajax4jsf.gwt.jsf.GwtEvent)
-	 */
-	public GwtFacesResult processEvent(GwtFacesEvent event) {
-		ELContext context = FacesContext.getCurrentInstance().getELContext();
-			GwtListener handler = getHandler(context);
-			return handler.processEvent(event);
-	}
-
-	/* (non-Javadoc)
-	 * @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object)
-	 */
-	public void restoreState(FacesContext context, Object state) {
-		State helperState = (State) state;
-		_binding = (ValueExpression) UIComponentBase.restoreAttachedState(context,helperState.binding);
-	}
-
-	/* (non-Javadoc)
-	 * @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
-	 */
-	public Object saveState(FacesContext context) {
-		State helperState = new State();
-		helperState.binding = UIComponentBase.saveAttachedState(context,_binding);
-		return helperState;
-	}
-
-	/**
-	 * @return Returns the transient.
-	 */
-	public boolean isTransient() {
-		return _transient;
-	}
-
-	/**
-	 * @param transient1 The transient to set.
-	 */
-	public void setTransient(boolean transient1) {
-		_transient = transient1;
-	}
-	
-	/**
-	 * @author shura
-	 *
-	 */
-	private static class State implements Serializable {
-		
-		
-		private Object binding;
-		
-
-	}
-
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.jsf;
+
+import java.io.Serializable;
+
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+
+import com.google.gwt.user.server.rpc.RPCRequest;
+
+/**
+ * @author shura
+ *
+ */
+public class GwtListenerHelper implements GwtListener, StateHolder {
+
+
+    private ValueExpression _binding;
+
+
+    private boolean _transient = false;
+
+
+    /**
+     *
+     */
+    public GwtListenerHelper() {
+        super();
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * @param binding
+     */
+    public GwtListenerHelper(ValueExpression binding) {
+        super();
+        if (null == binding) {
+            throw new IllegalArgumentException("Binding expression for GwtListener helper must be not null");
+        }
+        _binding = binding;
+    }
+
+    /* (non-Javadoc)
+      * @see org.ajax4jsf.gwt.jsf.GwtListener#isAcceptEvent(org.ajax4jsf.gwt.client.GwtFacesEvent)
+      */
+    public boolean canHandleRequest(RPCRequest request) {
+        ELContext context = FacesContext.getCurrentInstance().getELContext();
+        GwtListener handler = getHandler(context);
+        return handler.canHandleRequest(request);
+    }
+
+    private GwtListener getHandler(ELContext context) {
+        return (GwtListener) _binding.getValue(context);
+    }
+
+    /* (non-Javadoc)
+      * @see org.ajax4jsf.gwt.jsf.GwtListener#processCall(org.ajax4jsf.gwt.jsf.GwtEvent)
+      */
+    public String processRequest(RPCRequest request) {
+        ELContext context = FacesContext.getCurrentInstance().getELContext();
+        GwtListener handler = getHandler(context);
+        return handler.processRequest(request);
+    }
+
+    /* (non-Javadoc)
+      * @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object)
+      */
+    public void restoreState(FacesContext context, Object state) {
+        State helperState = (State) state;
+        _binding = (ValueExpression) UIComponentBase.restoreAttachedState(context,helperState.binding);
+    }
+
+    /* (non-Javadoc)
+      * @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
+      */
+    public Object saveState(FacesContext context) {
+        State helperState = new State();
+        helperState.binding = UIComponentBase.saveAttachedState(context,_binding);
+        return helperState;
+    }
+
+    /**
+     * @return Returns the transient.
+     */
+    public boolean isTransient() {
+        return _transient;
+    }
+
+    /**
+     * @param transient1 The transient to set.
+     */
+    public void setTransient(boolean transient1) {
+        _transient = transient1;
+    }
+
+    /**
+     * @author shura
+     *
+     */
+    private static class State implements Serializable {
+
+
+        private Object binding;
+
+
+    }
+
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerMethodHelper.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerMethodHelper.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerMethodHelper.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,143 +1,165 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.jsf;
-
-import java.io.Serializable;
-
-import javax.el.ELContext;
-import javax.el.MethodExpression;
-import javax.el.ValueExpression;
-import javax.faces.component.StateHolder;
-import javax.faces.component.UIComponentBase;
-import javax.faces.context.FacesContext;
-
-import org.ajax4jsf.gwt.client.GwtFacesEvent;
-import org.ajax4jsf.gwt.client.GwtFacesResult;
-
-/**
- * @author shura
- *
- */
-public class GwtListenerMethodHelper implements GwtListener,StateHolder {
-	
-	private MethodExpression _method;
-	
-	
-	private Class _eventType ;
-	
-	private boolean _transient = false;
-
-	
-	/**
-	 * 
-	 */
-	public GwtListenerMethodHelper() {
-		super();
-		// TODO Auto-generated constructor stub
-	}
-
-	/**
-	 * @param method
-	 * @param listenerType 
-	 */
-	public GwtListenerMethodHelper(MethodExpression method, Class listenerType) {
-		super();
-		if (null == method) {
-			throw new IllegalArgumentException("Method expression for GwtListener helper must be not null");
-		}
-		_method = method;
-		_eventType = listenerType;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.ajax4jsf.gwt.jsf.GwtListener#isAcceptEvent(org.ajax4jsf.gwt.client.GwtFacesEvent)
-	 */
-	public boolean isAcceptEvent(GwtFacesEvent event) {
-			if (null != _eventType) {
-				return _eventType.isInstance(event);
-			} else {
-				return true;
-			}
-	}
-
-	/* (non-Javadoc)
-	 * @see org.ajax4jsf.gwt.jsf.GwtListener#processEvent(org.ajax4jsf.gwt.jsf.GwtEvent)
-	 */
-	public GwtFacesResult processEvent(GwtFacesEvent event) {
-		ELContext context = FacesContext.getCurrentInstance().getELContext();
-		return (GwtFacesResult) _method.invoke(context,new Object[] { event });
-	}
-
-	/* (non-Javadoc)
-	 * @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object)
-	 */
-	public void restoreState(FacesContext context, Object state) {
-		State helperState = (State) state;
-		_method = (MethodExpression) UIComponentBase.restoreAttachedState(context,helperState.method);
-		_eventType = helperState.eventType;
-	}
-
-	/* (non-Javadoc)
-	 * @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
-	 */
-	public Object saveState(FacesContext context) {
-		State helperState = new State();
-		helperState.method = UIComponentBase.saveAttachedState(context,_method);
-		helperState.eventType = this._eventType;
-		return helperState;
-	}
-
-	/**
-	 * @return Returns the transient.
-	 */
-	public boolean isTransient() {
-		return _transient;
-	}
-
-	/**
-	 * @param transient1 The transient to set.
-	 */
-	public void setTransient(boolean transient1) {
-		_transient = transient1;
-	}
-	
-	/**
-	 * @author shura
-	 *
-	 */
-	private static class State implements Serializable {
-		
-		private Object method;
-		
-		
-		private Class  eventType ;
-
-	}
-
-	/**
-	 * @param eventType The eventType to set.
-	 */
-	public void setEventType(Class eventType) {
-		_eventType = eventType;
-	}
-
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.jsf;
+
+import java.io.Serializable;
+
+import javax.el.ELContext;
+import javax.el.MethodExpression;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+
+import org.ajax4jsf.gwt.client.GwtFacesEvent;
+import org.ajax4jsf.gwt.client.GwtFacesResult;
+import org.ajax4jsf.gwt.client.GwtFacesService;
+import org.ajax4jsf.gwt.client.GwtFacesException;
+import com.google.gwt.user.server.rpc.RPCRequest;
+import com.google.gwt.user.server.rpc.RPC;
+import com.google.gwt.user.server.rpc.UnexpectedException;
+import com.google.gwt.user.client.rpc.SerializationException;
+
+/**
+ * @author shura
+ *
+ */
+public class GwtListenerMethodHelper implements GwtListener, StateHolder, GwtFacesService {
+
+    private MethodExpression _method;
+
+
+    private Class _eventType ;
+
+    private boolean _transient = false;
+
+
+    /**
+     *
+     */
+    public GwtListenerMethodHelper() {
+        super();
+        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * @param method
+     * @param listenerType
+     */
+    public GwtListenerMethodHelper(MethodExpression method, Class listenerType) {
+        super();
+        if (null == method) {
+            throw new IllegalArgumentException("Method expression for GwtListener helper must be not null");
+        }
+        _method = method;
+        _eventType = listenerType;
+    }
+
+    /* (non-Javadoc)
+      * @see org.ajax4jsf.gwt.jsf.GwtListener#isAcceptEvent(org.ajax4jsf.gwt.client.GwtFacesEvent)
+      */
+    public boolean canHandleRequest(RPCRequest request) {
+        // Verify that it's a GWTFacesService call.
+        Class gwtFacesServiceClass = GwtFacesService.class;
+        Class requestClass = request.getMethod().getDeclaringClass();
+        // why is this not true here?????
+        if (!gwtFacesServiceClass.equals(requestClass)) {
+            return false;
+        }
+
+        if (!"sendEvent".equals(request.getMethod().getName())) {
+            return false;
+        }
+
+        if (request.getParameters().length != 1) {
+            return false;
+        }
+
+        Object event = request.getParameters()[0];
+
+        if (null != _eventType) {
+            return _eventType.isInstance(event);
+        } else {
+            return true;
+        }
+    }
+
+    /* (non-Javadoc)
+      * @see org.ajax4jsf.gwt.jsf.GwtListener#processCall(org.ajax4jsf.gwt.jsf.GwtEvent)
+      */
+    public String processRequest(RPCRequest request) {
+        // Invoke the call on this helper itself!
+        try {
+            return RPC.invokeAndEncodeResponse(this, request.getMethod(), request.getParameters());
+        } catch (SerializationException e) {
+            throw new RuntimeException("Could not deserialize request", e);
+        }
+    }
+
+
+    /**
+     * (non-Javadoc)
+     * @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object)
+     */
+    public void restoreState(FacesContext context, Object state) {
+        State helperState = (State) state;
+        _method = (MethodExpression) UIComponentBase.restoreAttachedState(context,helperState.method);
+        _eventType = helperState.eventType;
+    }
+
+    /* (non-Javadoc)
+      * @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
+      */
+    public Object saveState(FacesContext context) {
+        State helperState = new State();
+        helperState.method = UIComponentBase.saveAttachedState(context,_method);
+        helperState.eventType = this._eventType;
+        return helperState;
+    }
+
+    /**
+     * @return Returns the transient.
+     */
+    public boolean isTransient() {
+        return _transient;
+    }
+
+    /**
+     * @param transient1 The transient to set.
+     */
+    public void setTransient(boolean transient1) {
+        _transient = transient1;
+    }
+
+    /**
+     * Route the event through to the method.
+     * @param event
+     * @return
+     * @throws GwtFacesException
+     */
+    public GwtFacesResult sendEvent(GwtFacesEvent event) throws GwtFacesException {
+        ELContext context = FacesContext.getCurrentInstance().getELContext();
+        return (GwtFacesResult)_method.invoke(context, new Object[]{event});
+    }
+
+    /**
+     * @author shura
+     *
+     */
+    private static class State implements Serializable {
+
+        private Object method;
+
+
+        private Class  eventType ;
+
+    }
+
+    /**
+     * @param eventType The eventType to set.
+     */
+    public void setEventType(Class eventType) {
+        _eventType = eventType;
+    }
+
+}

Added: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerServiceHelper.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerServiceHelper.java	                        (rev 0)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtListenerServiceHelper.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -0,0 +1,117 @@
+package org.ajax4jsf.gwt.jsf;
+
+import com.google.gwt.user.server.rpc.RPCRequest;
+import com.google.gwt.user.server.rpc.RPC;
+import com.google.gwt.user.client.rpc.SerializationException;
+
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+import javax.el.ValueExpression;
+import javax.el.ELContext;
+import java.io.Serializable;
+
+/**
+ * GwtListener implementation that wraps a generic service bean.
+ *
+ * @author Rob Jellinghaus
+ */
+public class GwtListenerServiceHelper implements GwtListener, StateHolder {
+
+
+    private ValueExpression serviceBeanExpression;
+
+
+    private boolean _transient = false;
+
+
+    /**
+     * Default constructor; invoked by JSF view restore lifecycle.
+     */
+    public GwtListenerServiceHelper() {
+        super();
+    }
+
+    /**
+     * Constructor; invoked from GwtListenerHandler when constructing gwt:gwtListener tags.
+     * @param serviceBean
+     */
+    public GwtListenerServiceHelper(ValueExpression serviceBean) {
+        super();
+        if (null == serviceBean) {
+            throw new IllegalArgumentException("Binding expression for GwtListener helper must be not null");
+        }
+        this.serviceBeanExpression = serviceBean;
+    }
+
+    /**
+     * Can this service helper handle this request?  Implemented by inspecting the service bean to
+     * determine whether it implements the requested interface.
+     */
+    public boolean canHandleRequest(RPCRequest request) {
+        ELContext context = FacesContext.getCurrentInstance().getELContext();
+        Object serviceBean = getServiceBean(context);
+        Class requestInterface = request.getMethod().getDeclaringClass();
+        boolean interfaceIsSuperclassOf = requestInterface.isAssignableFrom(serviceBean.getClass());
+        return interfaceIsSuperclassOf;
+    }
+
+    private Object getServiceBean(ELContext context) {
+        return serviceBeanExpression.getValue(context);
+    }
+
+    /* (non-Javadoc)
+      * @see org.ajax4jsf.gwt.jsf.GwtListener#processCall(org.ajax4jsf.gwt.jsf.GwtEvent)
+      */
+    public String processRequest(RPCRequest request) {
+        ELContext context = FacesContext.getCurrentInstance().getELContext();
+        Object serviceBean = getServiceBean(context);
+        try {
+            return RPC.invokeAndEncodeResponse(serviceBean, request.getMethod(), request.getParameters());
+        } catch (SerializationException e) {
+            throw new RuntimeException("Couldn't serialize method response", e);
+        }
+    }
+
+    /* (non-Javadoc)
+      * @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object)
+      */
+    public void restoreState(FacesContext context, Object state) {
+        GwtListenerServiceHelper.State helperState = (GwtListenerServiceHelper.State) state;
+        serviceBeanExpression = (ValueExpression) UIComponentBase.restoreAttachedState(context,helperState.binding);
+    }
+
+    /* (non-Javadoc)
+      * @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
+      */
+    public Object saveState(FacesContext context) {
+        GwtListenerServiceHelper.State helperState = new GwtListenerServiceHelper.State();
+        helperState.binding = UIComponentBase.saveAttachedState(context,serviceBeanExpression);
+        return helperState;
+    }
+
+    /**
+     * @return Returns the transient.
+     */
+    public boolean isTransient() {
+        return _transient;
+    }
+
+    /**
+     * @param transient1 The transient to set.
+     */
+    public void setTransient(boolean transient1) {
+        _transient = transient1;
+    }
+
+    /**
+     * @author shura
+     *
+     */
+    private static class State implements Serializable {
+
+        private Object binding;
+
+    }
+
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtPhaseListener.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtPhaseListener.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/GwtPhaseListener.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,393 +1,375 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.jsf;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.StringReader;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.zip.GZIPOutputStream;
-
-import javax.faces.FacesException;
-import javax.faces.context.ExternalContext;
-import javax.faces.context.FacesContext;
-import javax.faces.event.PhaseEvent;
-import javax.faces.event.PhaseId;
-import javax.faces.event.PhaseListener;
-import javax.servlet.Servlet;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.ajax4jsf.gwt.client.ComponentEntryPoint;
-import org.ajax4jsf.gwt.server.GwtFacesServlet;
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-/**
- * Script pages handling
- * 
- * @author shura
- * 
- */
-public class GwtPhaseListener implements PhaseListener {
-	
-	private static final Logger _log = Logger.getLogger(GwtPhaseListener.class.getName());
-	
-	public static final String GWT_RESOURCE_PREFIX = "gwt/";
-
-	private static final class WebModuleConfigHandler extends DefaultHandler {
-		private  String _servletClassName = null;
-
-		/* (non-Javadoc)
-		 * @see org.xml.sax.helpers.DefaultHandler#resolveEntity(java.lang.String, java.lang.String)
-		 */
-		public InputSource resolveEntity(String publicId, String systemId) throws IOException, SAXException {
-			// Dummy resolver - disable all entity references
-			return new InputSource(new StringReader(""));
-		}
-
-		/* (non-Javadoc)
-		 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
-		 */
-		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
-			// TODO Auto-generated method stub
-			if ("servlet".equals(qName)) {
-				_servletClassName = attributes.getValue("class");
-			}
-		}
-
-		/**
-		 * @return Returns the servletClassName.
-		 */
-		String getServletClassName() {
-			return _servletClassName;
-		}
-	}
-
-	private static final int BUFFER_SIZE = 1024;
-
-	static protected final long DEFAULT_EXPIRE = 1000L * 60L * 60L * 12L;// 12
-																			// Hours
-
-	/**
-	 * Map contain gwt service servlet instances for different modules.
-	 */
-	private Map serviceServlets = Collections.synchronizedMap(new HashMap());
-
-	private Servlet _defaultSrviceServlet;
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.event.PhaseListener#afterPhase(javax.faces.event.PhaseEvent)
-	 */
-	public void afterPhase(PhaseEvent event) {
-		// Check for request type - in case of google RPC call, forward to
-		// service servlet.
-		// headerMap must contain x-gwtcallingmodule='module name'
-		// content-type=text/plain; charset=utf-8
-		FacesContext facesContext = event.getFacesContext();
-		ExternalContext externalContext = facesContext.getExternalContext();
-		String requestContentType = externalContext.getRequestContentType();
-		Map requestParameterMap = externalContext.getRequestParameterMap();
-		if (null != requestContentType
-				&& requestContentType.contains("text/plain")) {
-			// GWT module name. Due to differences in browsers and containers, compare with ignore case.
-			String module = (String) requestParameterMap.get(ComponentEntryPoint.GWT_MODULE_NAME_PARAMETER);
-			Servlet servletForModule;
-			if(null != module){
-					servletForModule = getServletForModule(facesContext, module);
-			} else {
-					servletForModule = getDefaultServiceServlet(facesContext);
-			}
-					try {
-						servletForModule.service((ServletRequest) externalContext
-								.getRequest(), (ServletResponse) externalContext
-								.getResponse());
-					} catch (ServletException e) {
-						_log.severe("Servlet exception in GWT service method "+e.getMessage());
-						throw new FacesException(
-								"Servlet exception in GWT service method", e);
-					} catch (IOException e) {
-						_log.severe("IO exception in GWT service method "+e.getMessage());
-						throw new FacesException("IO exception in GWT service method",
-								e);
-					}
-					facesContext.responseComplete();
-		}
-		// Map requestParameterMap = externalContext.getRequestParameterMap();
-	}
-
-	/**
-	 * Get GWT RPC service servlet instance for module
-	 * 
-	 * @param context
-	 * @param moduleName
-	 * @return
-	 */
-	private Servlet getServletForModule(FacesContext context, String moduleName) {
-		// First - check for existing instances
-		if (serviceServlets.containsKey(moduleName)) {
-			if (_log.isLoggable(Level.FINE)) {
-				_log.fine("Found existing servlet for module "+moduleName);
-			}
-			return (Servlet) serviceServlets.get(moduleName);
-		}
-		// Second -attempt to read module config and, if in contain servlet
-		// definition -
-		// create instance and store in Map
-		String servletClass = getServletClassForModule(moduleName);
-		if(null != servletClass){
-			Servlet servlet = createServlet(context,servletClass);
-			serviceServlets.put(moduleName,servlet);
-			if (_log.isLoggable(Level.FINE)) {
-				_log.fine("Create new servlet for module "+moduleName+" with class "+servletClass);
-			}
-			return servlet;
-		}
-		// last - return default service servlet
-		Servlet defaultServiceServlet = getDefaultServiceServlet(context);
-		serviceServlets.put(moduleName,defaultServiceServlet);
-		if (_log.isLoggable(Level.FINE)) {
-			_log.fine("Use default servlet for module "+moduleName);
-		}
-		return defaultServiceServlet;
-	}
-
-	private String getServletClassForModule(String moduleName) {
-		ClassLoader classLoader = Thread.currentThread()
-		.getContextClassLoader();
-		String servletClassName = null;
-		// for module foo.bar.Module config file will be placed at foo/bar/Module.gwt.xml
-		String gwtModuleConfigPath = moduleName.replace('.','/')+".gwt.xml";
-		InputStream stream = classLoader.getResourceAsStream(gwtModuleConfigPath);
-		if(null != stream){
-			// We have module confir to read - parce it for servlen name.
-			SAXParserFactory parserFactory = SAXParserFactory.newInstance();
-			try {
-				SAXParser parser = parserFactory.newSAXParser();
-				WebModuleConfigHandler handler = new WebModuleConfigHandler();
-				parser.parse(stream,handler);
-				servletClassName = handler.getServletClassName();
-			} catch (Exception e) {
-				if (_log.isLoggable(Level.WARNING)) {
-					_log.warning("Exception in parsing web module config "+e.getMessage());
-				}
-			}
-		}
-		return servletClassName;
-	}
-
-	/**
-	 * Create and initialize instance for servlet from class
-	 * 
-	 * @param context
-	 * @param className
-	 *            name of servlet class.
-	 * @return
-	 */
-	private Servlet createServlet(FacesContext context, String className) {
-		ClassLoader classLoader = Thread.currentThread()
-				.getContextClassLoader();
-		try {
-			Class clazz = classLoader.loadClass(className);
-			Servlet servlet = (Servlet) clazz.newInstance();
-			final ServletContext servletContext = (ServletContext) context.getExternalContext()
-			.getContext();
-			servlet.init(new ServletConfig() {
-
-				public String getServletName() {
-					// TODO Auto-generated method stub
-					return "gwtFacesService";
-				}
-
-				public ServletContext getServletContext() {
-					// TODO Auto-generated method stub
-					return servletContext;
-				}
-
-				public String getInitParameter(String arg0) {
-					// TODO Auto-generated method stub
-					return null;
-				}
-
-				public Enumeration getInitParameterNames() {
-					// TODO Auto-generated method stub
-					return null;
-				}
-			});
-			return servlet;
-		} catch (Exception e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-			throw new FacesException("Error to create gwt service servlet", e);
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.event.PhaseListener#beforePhase(javax.faces.event.PhaseEvent)
-	 */
-	public void beforePhase(PhaseEvent event) {
-		// check for script name.
-		FacesContext facesContext = event.getFacesContext();
-		ExternalContext externalContext = facesContext.getExternalContext();
-		String mime = "text/html";
-		String resourceName = null;
-		// assume that mapping have /faces/* prefix
-		String pathInfo = externalContext
-				.getRequestPathInfo();
-		
-		if (null != pathInfo   ) {
-			if(pathInfo.charAt(0) == '/'){
-				pathInfo = pathInfo.substring(1);
-			}
-			if (pathInfo.startsWith(GWT_RESOURCE_PREFIX) ) {
-				resourceName = pathInfo;
-				if (pathInfo.endsWith(".js")) {
-					mime = "text/javascript";
-				} else if (pathInfo.endsWith(".xml")) {
-					// xml with module cache entries
-					mime = "text/xml";
-				} else if (pathInfo.endsWith(".css")) {
-					// xml with module cache entries
-					mime = "text/css";
-				} else if (pathInfo.endsWith(".gif")) {
-					mime = "image/gif";
-				} else if (pathInfo.endsWith(".jpg")
-						|| pathInfo.endsWith(".jpeg")) {
-					mime = "image/jpeg";
-				} else {
-					// normal request - do nothing
-					//				return;
-				}
-				// we have resource - send it.
-				try {
-					HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
-					ClassLoader loader = Thread.currentThread()
-							.getContextClassLoader();
-					InputStream in = loader.getResourceAsStream("META-INF/"
-							+ resourceName);
-					
-					if (null != in) {
-						OutputStream out = response.getOutputStream();
-						response.setContentType(mime);
-						// Set cachimg/nocaching headers.
-						
-						if (resourceName.endsWith(".nocache.html")) {
-							response.setHeader("Cache-control", "no-cache");
-							response.setHeader("Cache-control", "no-store");
-							response.setHeader("Pragma", "no-cache");
-							response.setIntHeader("Expires", 0);
-						} else if (resourceName.contains(".cache.")){
-							// TODO - send notmodified if request contain If-Modified-Since
-							// ?
-							HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
-							long ifModifiedSince = request
-								.getDateHeader("If-Modified-Since");
-								if (ifModifiedSince >= 0) {
-									response.setStatus(304);// Not modified
-									in.close();
-									out.close();
-									facesContext.responseComplete();
-									return ;
-								} else {
-									response.setDateHeader("Expires", System
-											.currentTimeMillis()
-											+ DEFAULT_EXPIRE);
-								}
-						}
-						// Set output compression
-						if(mime.contains("text") || mime.contains("xml")){
-						String encoding = (String) externalContext.getRequestHeaderMap().get("Accept-Encoding");
-						if(null != encoding && encoding.contains("gzip")){
-							// TODO - use cache ?
-							response.setHeader("Content-Encoding","gzip");
-							out = new GZIPOutputStream(out,BUFFER_SIZE);
-						}
-						}
-						byte[] buffer = new byte[BUFFER_SIZE];
-						int buffersCount = -1;
-						int length;
-						for (length = in.read(buffer); length > 0; length = in
-								.read(buffer)) {
-							out.write(buffer, 0, length);
-							buffersCount++;
-						}
-						// For cacheable resources, store size.
-						// if(isCacheable()){
-						// setContentLength(buffersCount*BUFFER_SIZE+length);
-						// }
-						in.close();
-						out.flush();
-						out.close();
-					} else {
-						response.sendError(404);
-					}
-				} catch (IOException e) {
-					throw new FacesException("Error then send resource", e);
-				} finally {
-					facesContext.responseComplete();
-				}
-			}
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.event.PhaseListener#getPhaseId()
-	 */
-	public PhaseId getPhaseId() {
-		// TODO Auto-generated method stub
-		return PhaseId.RESTORE_VIEW;
-	}
-
-	/**
-	 * @return Returns the defaultSrviceServlet.
-	 */
-	public Servlet getDefaultServiceServlet(FacesContext context) {
-		if (_defaultSrviceServlet == null) {
-			_defaultSrviceServlet = createServlet(context,
-					GwtFacesServlet.class.getName());
-		}
-		return _defaultSrviceServlet;
-	}
-
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.jsf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringReader;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.GZIPOutputStream;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.ajax4jsf.gwt.client.ComponentEntryPoint;
+import org.ajax4jsf.gwt.server.GwtFacesServlet;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Handle GWT requests during the RESTORE_VIEW phase.  Requests coming into the
+ * FacesServlet that begin with "gwt/" will cause straight classpath resource retrieval
+ * ending with responseComplete (in the beforePhase method).  Requests coming in to a
+ * GWT service endpoint URL will get delegated to the appropriate GWT service servlet
+ * (in the afterPhase method).
+ *
+ * @author shura
+ */
+public class GwtPhaseListener implements PhaseListener {
+	
+	private static final Logger _log = Logger.getLogger(GwtPhaseListener.class.getName());
+	
+	public static final String GWT_RESOURCE_PREFIX = "gwt/";
+
+	private static final class WebModuleConfigHandler extends DefaultHandler {
+		private  String _servletClassName = null;
+
+		/* (non-Javadoc)
+		 * @see org.xml.sax.helpers.DefaultHandler#resolveEntity(java.lang.String, java.lang.String)
+		 */
+		public InputSource resolveEntity(String publicId, String systemId) throws IOException, SAXException {
+			// Dummy resolver - disable all entity references
+			return new InputSource(new StringReader(""));
+		}
+
+		/* (non-Javadoc)
+		 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
+		 */
+		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+			// TODO Auto-generated method stub
+			if ("servlet".equals(qName)) {
+				_servletClassName = attributes.getValue("class");
+			}
+		}
+
+		/**
+		 * @return Returns the servletClassName.
+		 */
+		String getServletClassName() {
+			return _servletClassName;
+		}
+	}
+
+	private static final int BUFFER_SIZE = 1024;
+
+	static protected final long DEFAULT_EXPIRE = 1000L * 60L * 60L * 12L;// 12
+																			// Hours
+
+	/**
+	 * Map contain gwt service servlet instances for different modules.
+	 */
+	private Map serviceServlets = Collections.synchronizedMap(new HashMap());
+
+	private Servlet _defaultServiceServlet;
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.faces.event.PhaseListener#afterPhase(javax.faces.event.PhaseEvent)
+	 */
+	public void afterPhase(PhaseEvent event) {
+		// Check for request type - in case of google RPC call, forward to
+		// service servlet.
+		// headerMap must contain x-gwtcallingmodule='module name'
+		// content-type=text/plain; charset=utf-8
+		FacesContext facesContext = event.getFacesContext();
+		ExternalContext externalContext = facesContext.getExternalContext();
+		String requestContentType = externalContext.getRequestContentType();
+		Map requestParameterMap = externalContext.getRequestParameterMap();
+		if (null != requestContentType
+				&& requestContentType.contains("text/plain")) {
+			// GWT module name. Due to differences in browsers and containers, compare with ignore case.
+			String module = (String) requestParameterMap.get(ComponentEntryPoint.GWT_MODULE_NAME_PARAMETER);
+			Servlet servletForModule;
+			if(null != module){
+					servletForModule = getServletForModule(facesContext, module);
+			} else {
+					servletForModule = getDefaultServiceServlet(facesContext);
+			}
+					try {
+						servletForModule.service((ServletRequest) externalContext
+								.getRequest(), (ServletResponse) externalContext
+								.getResponse());
+					} catch (ServletException e) {
+						_log.severe("Servlet exception in GWT service method "+e.getMessage());
+						throw new FacesException(
+								"Servlet exception in GWT service method", e);
+					} catch (IOException e) {
+						_log.severe("IO exception in GWT service method "+e.getMessage());
+						throw new FacesException("IO exception in GWT service method",
+								e);
+					}
+					facesContext.responseComplete();
+		}
+		// Map requestParameterMap = externalContext.getRequestParameterMap();
+	}
+
+	/**
+	 * Get GWT RPC service servlet instance for module
+	 * 
+	 * @param context
+	 * @param moduleName
+	 */
+	private Servlet getServletForModule(FacesContext context, String moduleName) {
+		// First - check for existing instances
+		if (serviceServlets.containsKey(moduleName)) {
+			if (_log.isLoggable(Level.FINE)) {
+				_log.fine("Found existing servlet for module "+moduleName);
+			}
+			return (Servlet) serviceServlets.get(moduleName);
+		}
+		// Second -attempt to read module config and, if in contain servlet
+		// definition -
+		// create instance and store in Map
+		String servletClass = getServletClassForModule(moduleName);
+		if(null != servletClass){
+			Servlet servlet = createServlet(context,servletClass);
+			serviceServlets.put(moduleName,servlet);
+			if (_log.isLoggable(Level.FINE)) {
+				_log.fine("Create new servlet for module "+moduleName+" with class "+servletClass);
+			}
+			return servlet;
+		}
+		// last - return default service servlet
+		Servlet defaultServiceServlet = getDefaultServiceServlet(context);
+		serviceServlets.put(moduleName,defaultServiceServlet);
+		if (_log.isLoggable(Level.FINE)) {
+			_log.fine("Use default servlet for module "+moduleName);
+		}
+		return defaultServiceServlet;
+	}
+
+	private String getServletClassForModule(String moduleName) {
+		ClassLoader classLoader = Thread.currentThread()
+		.getContextClassLoader();
+		String servletClassName = null;
+		// for module foo.bar.Module config file will be placed at foo/bar/Module.gwt.xml
+		String gwtModuleConfigPath = moduleName.replace('.','/')+".gwt.xml";
+		InputStream stream = classLoader.getResourceAsStream(gwtModuleConfigPath);
+		if(null != stream){
+			// We have module confir to read - parce it for servlen name.
+			SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+			try {
+				SAXParser parser = parserFactory.newSAXParser();
+				WebModuleConfigHandler handler = new WebModuleConfigHandler();
+				parser.parse(stream,handler);
+				servletClassName = handler.getServletClassName();
+			} catch (Exception e) {
+				if (_log.isLoggable(Level.WARNING)) {
+					_log.warning("Exception in parsing web module config "+e.getMessage());
+				}
+			}
+		}
+		return servletClassName;
+	}
+
+	/**
+	 * Create and initialize instance for servlet from class
+	 * 
+	 * @param context
+	 * @param className
+	 *            name of servlet class.
+	 */
+	private Servlet createServlet(FacesContext context, String className) {
+		ClassLoader classLoader = Thread.currentThread()
+				.getContextClassLoader();
+		try {
+			Class clazz = classLoader.loadClass(className);
+			Servlet servlet = (Servlet) clazz.newInstance();
+			final ServletContext servletContext = (ServletContext) context.getExternalContext()
+			.getContext();
+			servlet.init(new ServletConfig() {
+
+				public String getServletName() {
+					// TODO Auto-generated method stub
+					return "gwtFacesService";
+				}
+
+				public ServletContext getServletContext() {
+					// TODO Auto-generated method stub
+					return servletContext;
+				}
+
+				public String getInitParameter(String arg0) {
+					// TODO Auto-generated method stub
+					return null;
+				}
+
+				public Enumeration getInitParameterNames() {
+					// TODO Auto-generated method stub
+					return null;
+				}
+			});
+			return servlet;
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			throw new FacesException("Error to create gwt service servlet", e);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.faces.event.PhaseListener#beforePhase(javax.faces.event.PhaseEvent)
+	 */
+	public void beforePhase(PhaseEvent event) {
+		// check for script name.
+		FacesContext facesContext = event.getFacesContext();
+		ExternalContext externalContext = facesContext.getExternalContext();
+		String mime = "text/html";
+		String resourceName = null;
+		// assume that mapping have /faces/* prefix
+		String pathInfo = externalContext
+				.getRequestPathInfo();
+		
+		if (null != pathInfo   ) {
+			if(pathInfo.charAt(0) == '/'){
+				pathInfo = pathInfo.substring(1);
+			}
+			if (pathInfo.startsWith(GWT_RESOURCE_PREFIX) ) {
+				resourceName = pathInfo;
+				if (pathInfo.endsWith(".js")) {
+					mime = "text/javascript";
+				} else if (pathInfo.endsWith(".xml")) {
+					// xml with module cache entries
+					mime = "text/xml";
+				} else if (pathInfo.endsWith(".css")) {
+					// xml with module cache entries
+					mime = "text/css";
+				} else if (pathInfo.endsWith(".gif")) {
+					mime = "image/gif";
+				} else if (pathInfo.endsWith(".jpg")
+						|| pathInfo.endsWith(".jpeg")) {
+					mime = "image/jpeg";
+				} else {
+					// normal request - do nothing
+					//				return;
+				}
+				// we have resource - send it.
+				try {
+					HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
+					ClassLoader loader = Thread.currentThread()
+							.getContextClassLoader();
+					InputStream in = loader.getResourceAsStream("META-INF/"
+							+ resourceName);
+					
+					if (null != in) {
+						OutputStream out = response.getOutputStream();
+						response.setContentType(mime);
+						// Set cachimg/nocaching headers.
+						
+						if (resourceName.endsWith(".nocache.html")) {
+							response.setHeader("Cache-control", "no-cache");
+							response.setHeader("Cache-control", "no-store");
+							response.setHeader("Pragma", "no-cache");
+							response.setIntHeader("Expires", 0);
+						} else if (resourceName.contains(".cache.")){
+							// TODO - send notmodified if request contain If-Modified-Since
+							// ?
+							HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
+							long ifModifiedSince = request
+								.getDateHeader("If-Modified-Since");
+								if (ifModifiedSince >= 0) {
+									response.setStatus(304);// Not modified
+									in.close();
+									out.close();
+									facesContext.responseComplete();
+									return ;
+								} else {
+									response.setDateHeader("Expires", System
+											.currentTimeMillis()
+											+ DEFAULT_EXPIRE);
+								}
+						}
+						// Set output compression
+						if(mime.contains("text") || mime.contains("xml")){
+						String encoding = (String) externalContext.getRequestHeaderMap().get("Accept-Encoding");
+						if(null != encoding && encoding.contains("gzip")){
+							// TODO - use cache ?
+							response.setHeader("Content-Encoding","gzip");
+							out = new GZIPOutputStream(out,BUFFER_SIZE);
+						}
+						}
+						byte[] buffer = new byte[BUFFER_SIZE];
+						int buffersCount = -1;
+						int length;
+						for (length = in.read(buffer); length > 0; length = in
+								.read(buffer)) {
+							out.write(buffer, 0, length);
+							buffersCount++;
+						}
+						// For cacheable resources, store size.
+						// if(isCacheable()){
+						// setContentLength(buffersCount*BUFFER_SIZE+length);
+						// }
+						in.close();
+						out.flush();
+						out.close();
+					} else {
+						response.sendError(404);
+					}
+				} catch (IOException e) {
+					throw new FacesException("Error then send resource", e);
+				} finally {
+					facesContext.responseComplete();
+				}
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.faces.event.PhaseListener#getPhaseId()
+	 */
+	public PhaseId getPhaseId() {
+		// TODO Auto-generated method stub
+		return PhaseId.RESTORE_VIEW;
+	}
+
+	/**
+	 * @return Returns the defaultServiceServlet.
+	 */
+	public Servlet getDefaultServiceServlet(FacesContext context) {
+		if (_defaultServiceServlet == null) {
+			_defaultServiceServlet = createServlet(context,
+					GwtFacesServlet.class.getName());
+		}
+		return _defaultServiceServlet;
+	}
+
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/PageRenderer.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/PageRenderer.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/PageRenderer.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,187 +1,211 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.jsf;
-
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import javax.faces.component.UIComponent;
-import javax.faces.context.FacesContext;
-import javax.faces.context.ResponseWriter;
-import javax.faces.render.Renderer;
-
-/**
- * @author shura
- * 
- */
-public class PageRenderer extends Renderer {
-	
-	public static final String FACES_SERVLET_PREFIX_PARAM = "org.ajax4jsg.gwt.SCRIPT_PREFIX";
-
-	private static final String RENDERED_FLAG_BASE = "org.ajax4jsf.gwt.rendered.";
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext,
-	 *      javax.faces.component.UIComponent)
-	 */
-	public void encodeBegin(FacesContext context, UIComponent component)
-			throws IOException {
-		super.encodeBegin(context, component);
-		ResponseWriter writer = context.getResponseWriter();
-		Map attributes = component.getAttributes();
-		writer.startElement("html", component);
-		writer.startElement("head", component);
-		Object title = attributes.get("title");
-		if (null != title) {
-			writer.startElement("title", component);
-			writer.writeText(title, "title");
-			writer.endElement("title");
-
-		}
-		UIComponent head = component.getFacet("head");
-		if (null != head) {
-			head.encodeAll(context);
-		}
-		String scriptsBase = getScriptBase(context);
-		// Used GWT modules
-		Set modules = findGwtModules(context, component);
-		for (Iterator iter = modules.iterator(); iter.hasNext();) {
-			String moduleName = (String) iter.next();
-			writeModule(context, scriptsBase, moduleName);
-		}
-		writeScriptAndParameters(context);
-
-		writer.endElement("head");
-		writer.startElement("body", component);
-		// Navigation history iframe
-		writeHistoryFrame(context);
-	}
-
-	/**
-	 * @param writer
-	 * @throws IOException
-	 */
-	public static void writeHistoryFrame(FacesContext context) throws IOException {
-		String renderedFlag = RENDERED_FLAG_BASE+"history";
-		Map requestMap = context.getExternalContext().getRequestMap();
-		Object rendered = requestMap.get(renderedFlag);
-		if (rendered == null) {
-			requestMap.put(renderedFlag, Boolean.TRUE);
-		ResponseWriter writer = context.getResponseWriter();
-		writer.startElement("iframe", null);
-		writer.writeAttribute("id", "__gwt_historyFrame", null);
-		writer.writeAttribute("style", "width:0;height:0;border:0", null);
-		writer.endElement("iframe");
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext,
-	 *      javax.faces.component.UIComponent)
-	 */
-	public void encodeEnd(FacesContext context, UIComponent component)
-			throws IOException {
-		super.encodeEnd(context, component);
-		ResponseWriter writer = context.getResponseWriter();
-		writer.endElement("body");
-		writer.endElement("html");
-	}
-
-	private Set findGwtModules(FacesContext context, UIComponent component) {
-		Set found = new HashSet();
-		if (component instanceof GwtComponent) {
-			found.add(((GwtComponent) component).getModuleName());
-		}
-		for (Iterator iter = component.getFacetsAndChildren(); iter.hasNext();) {
-			UIComponent child = (UIComponent) iter.next();
-			found.addAll(findGwtModules(context, child));
-		}
-		return found;
-	}
-	
-	public static void writeScriptAndParameters(FacesContext context) throws IOException{
-		String renderedFlag = RENDERED_FLAG_BASE+"script";
-		Map requestMap = context.getExternalContext().getRequestMap();
-		Object rendered = requestMap.get(renderedFlag);
-		if (rendered == null) {
-			requestMap.put(renderedFlag, Boolean.TRUE);
-			ResponseWriter writer = context.getResponseWriter();
-			String viewId = context.getViewRoot().getViewId();
-			writeGwtProperty(writer, "viewid", viewId);
-			Locale locale = context.getViewRoot().getLocale();
-			writeGwtProperty(writer, "locale", locale.toString());
-			String action = context.getApplication().getViewHandler().getActionURL(
-					context, viewId);
-			action = context.getExternalContext().encodeActionURL(action);
-			writeGwtProperty(writer, "action", action);
-			String scriptsBase = getScriptBase(context);
-			writeGwtProperty(writer, "base", scriptsBase);
-			// GWT Script
-			writer.startElement("script", null);
-			writer.writeAttribute("language", "javascript", null);
-			writer.writeAttribute("src", scriptsBase+"gwt.js", null);
-			writer.endElement("script");
-		}
-	}
-
-	public static void writeModule(FacesContext context, String base,String name) throws IOException{
-		String renderedFlag = RENDERED_FLAG_BASE+name;
-		Map requestMap = context.getExternalContext().getRequestMap();
-		Object rendered = requestMap.get(renderedFlag);
-		if (rendered == null) {
-			requestMap.put(renderedFlag, Boolean.TRUE);
-			ResponseWriter writer = context.getResponseWriter();
-			writeMeta(writer, "gwt:module", base+name+"="+name);
-		}
-	}
-	/**
-	 * @param context
-	 * @return
-	 */
-	public static String getScriptBase(FacesContext context) {
-		String resourcesPrefix = context.getExternalContext().getInitParameter(FACES_SERVLET_PREFIX_PARAM);
-		if( null == resourcesPrefix){
-			resourcesPrefix = "/faces/";
-		}
-		String scriptsBase = context.getApplication().getViewHandler().getResourceURL(context,resourcesPrefix+GwtPhaseListener.GWT_RESOURCE_PREFIX);
-		return scriptsBase;
-	}
-	
-	private static void writeGwtProperty(ResponseWriter writer, String name,String value) throws IOException{
-		writeMeta(writer, "gwt:property", name+"="+value);
-	}
-	
-	private static void writeMeta(ResponseWriter writer, String name,String value) throws IOException{
-		writer.startElement("meta", null);
-		writer.writeAttribute("name", name, null);
-		writer.writeAttribute("content", value, null);
-		writer.endElement("meta");
-
-	}
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.jsf;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.render.Renderer;
+
+/**
+ * Render a gwt:page tag.  Scrapes the component tree for GWT components, and adds the
+ * appropriate meta tags to the header.  Also creates the GWT script tag as the last child
+ * of the head, and the history iframe as the first child of the body.
+ * @author shura
+ */
+public class PageRenderer extends Renderer {
+
+    public static final String FACES_SERVLET_PREFIX_PARAM = "org.ajax4jsg.gwt.SCRIPT_PREFIX";
+
+    private static final String RENDERED_FLAG_BASE = "org.ajax4jsf.gwt.rendered.";
+    /*
+      * (non-Javadoc)
+      *
+      * @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext,
+      *      javax.faces.component.UIComponent)
+      */
+    public void encodeBegin(FacesContext context, UIComponent component)
+            throws IOException {
+        super.encodeBegin(context, component);
+
+        ResponseWriter writer = context.getResponseWriter();
+        Map attributes = component.getAttributes();
+        writer.startElement("html", component);
+
+        // added by RobJ for Facelets compatibility
+        writer.writeAttribute("xmlns", "http://www.w3.org/1999/xhtml", null);
+
+        writer.startElement("head", component);
+
+        UIComponent head = component.getFacet("head");
+        if (null != head) {
+            head.encodeAll(context);
+        }
+
+        Object title = attributes.get("title");
+        if (null != title) {
+            writer.startElement("title", component);
+            writer.writeText(title, "title");
+            writer.endElement("title");
+        }
+
+        String scriptsBase = getScriptBase(context);
+        writeParameters(context);
+
+        writer.endElement("head");
+        writer.startElement("body", component);
+
+        // Used GWT modules
+        Set modules = findGwtModules(context, component);
+        for (Iterator iter = modules.iterator(); iter.hasNext();) {
+            String moduleName = (String) iter.next();
+            writeModule(context, scriptsBase, moduleName);
+        }
+
+        // Navigation history iframe
+        writeHistoryFrame(context);
+
+    }
+
+    /**
+     * Write the GWT history frame.  Expects to be the first element in the body.
+     * @throws IOException
+     */
+    public static void writeHistoryFrame(FacesContext context) throws IOException {
+        String renderedFlag = RENDERED_FLAG_BASE+"history";
+        Map requestMap = context.getExternalContext().getRequestMap();
+        Object rendered = requestMap.get(renderedFlag);
+        if (rendered == null) {
+            requestMap.put(renderedFlag, Boolean.TRUE);
+            ResponseWriter writer = context.getResponseWriter();
+            writer.startElement("iframe", null);
+            writer.writeAttribute("id", "__gwt_historyFrame", null);
+            writer.writeAttribute("style", "width:0;height:0;border:0", null);
+            writer.endElement("iframe");
+        }
+    }
+
+    /*
+      * (non-Javadoc)
+      *
+      * @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext,
+      *      javax.faces.component.UIComponent)
+      */
+    public void encodeEnd(FacesContext context, UIComponent component)
+            throws IOException {
+        super.encodeEnd(context, component);
+        ResponseWriter writer = context.getResponseWriter();
+        writer.endElement("body");
+        writer.endElement("html");
+    }
+
+    private Set findGwtModules(FacesContext context, UIComponent component) {
+        Set found = new HashSet();
+        if (component instanceof GwtComponent) {
+            found.add(((GwtComponent) component).getModuleName());
+        }
+        for (Iterator iter = component.getFacetsAndChildren(); iter.hasNext();) {
+            UIComponent child = (UIComponent) iter.next();
+            found.addAll(findGwtModules(context, child));
+        }
+        return found;
+    }
+
+    /**
+     * Write all necessary GWT properties and parameters as meta tags.
+     * @param context
+     * @throws IOException
+     */
+    public static void writeParameters(FacesContext context) throws IOException{
+        String renderedFlag = RENDERED_FLAG_BASE+"script";
+        Map requestMap = context.getExternalContext().getRequestMap();
+        Object rendered = requestMap.get(renderedFlag);
+        if (rendered == null) {
+            requestMap.put(renderedFlag, Boolean.TRUE);
+            ResponseWriter writer = context.getResponseWriter();
+            String viewId = context.getViewRoot().getViewId();
+            writeGwtProperty(writer, "viewid", viewId);
+            Locale locale = context.getViewRoot().getLocale();
+            writeGwtProperty(writer, "locale", locale.toString());
+            String action = context.getApplication().getViewHandler().getActionURL(
+                    context, viewId);
+            action = context.getExternalContext().encodeActionURL(action);
+            writeGwtProperty(writer, "action", action);
+            String scriptsBase = getScriptBase(context);
+            writeGwtProperty(writer, "base", scriptsBase);
+        }
+    }
+
+    /**
+     * Write the module script tag.  This will load the "selection script" (GWT developer
+     * terminology) for the module.  The path in the script element will be something like
+     * /webappname/faces/gwt/modulename/modulename.nocache.js.
+     */
+    public static void writeModule(FacesContext context, String base,String name) throws IOException{
+        String renderedFlag = RENDERED_FLAG_BASE+name;
+        Map requestMap = context.getExternalContext().getRequestMap();
+        Object rendered = requestMap.get(renderedFlag);
+        if (rendered == null) {
+            requestMap.put(renderedFlag, Boolean.TRUE);
+            ResponseWriter writer = context.getResponseWriter();
+
+            String scriptsBase = getScriptBase(context);
+
+            // Marker script BEFORE the actual script, to work around weird Firefox issue with
+            // adding it from the selection script computeScriptBase function.
+            // Marker script looks like:  <script id="__gwt_marker_demo.gwt.HelloWidget"></script>
+            writer.startElement("script", null);
+            writer.writeAttribute("language", "javascript", null);
+            writer.writeAttribute("id", "__gwt_js_marker_" + name, null);
+            writer.endElement("script");
+
+            // Write the selection script
+            writer.startElement("script", null);
+            writer.writeAttribute("language", "javascript", null);
+            writer.writeAttribute("src", scriptsBase + name + "/" + name + ".nocache.js", null);
+            writer.endElement("script");
+
+
+        }
+    }
+
+    /**
+     * Get the base URL for scripts.  This will in general be something like "/webappname/faces/gwt".
+     * @param context
+     */
+    public static String getScriptBase(FacesContext context) {
+        String resourcesPrefix = context.getExternalContext().getInitParameter(FACES_SERVLET_PREFIX_PARAM);
+        if( null == resourcesPrefix){
+            resourcesPrefix = "/faces/";
+        }
+        String scriptsBase = context.getApplication().getViewHandler().getResourceURL(context,resourcesPrefix+GwtPhaseListener.GWT_RESOURCE_PREFIX);
+        return scriptsBase;
+    }
+
+    /**
+     * Write a GWT meta property.  Meta properties are meta elements with name="gwt:property" and
+     * content="name=value".
+     */
+    private static void writeGwtProperty(ResponseWriter writer, String name, String value) throws IOException{
+        writeMeta(writer, "gwt:property", name+"="+value);
+    }
+
+    /**
+     * Write a meta element directly to the response.
+     */
+    private static void writeMeta(ResponseWriter writer, String name, String content) throws IOException{
+        writer.startElement("meta", null);
+        writer.writeAttribute("name", name, null);
+        writer.writeAttribute("content", content, null);
+        writer.endElement("meta");
+
+    }
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/WidgetRenderer.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/WidgetRenderer.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/jsf/WidgetRenderer.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,385 +1,367 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.jsf;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.el.ValueExpression;
-import javax.faces.FacesException;
-import javax.faces.component.ActionSource;
-import javax.faces.component.EditableValueHolder;
-import javax.faces.component.UIComponent;
-import javax.faces.component.ValueHolder;
-import javax.faces.context.FacesContext;
-import javax.faces.context.ResponseWriter;
-import javax.faces.convert.Converter;
-import javax.faces.convert.ConverterException;
-import javax.faces.render.Renderer;
-
-/**
- * @author shura
- * 
- */
-public class WidgetRenderer extends Renderer {
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext,
-	 *      javax.faces.component.UIComponent)
-	 */
-	public void decode(FacesContext context, UIComponent component) {
-		// TODO Auto-generated method stub
-		super.decode(context, component);
-		String clientId = component.getClientId(context);
-		Map requestParameterMap = context.getExternalContext()
-				.getRequestParameterMap();
-		Object parameter;
-		String paramName;
-		if (component instanceof ActionSource) {
-			if (component instanceof UIWidget) {
-				paramName = clientId + ((UIWidget) component).getActionParam();
-			} else {
-				paramName = clientId;
-			}
-			parameter = requestParameterMap.get(paramName);
-			if (null != parameter) {
-
-				// ActionSource action = (ActionSource) component;
-				component.queueEvent(new GwtActionEvent(component, parameter));
-			}
-		}
-		if (component instanceof EditableValueHolder) {
-			if (component instanceof UIWidget) {
-				paramName = clientId + ((UIWidget) component).getInputParam();
-			} else {
-				paramName = clientId;
-			}
-			parameter = requestParameterMap.get(paramName);
-			if (null != parameter) {
-				EditableValueHolder editable = (EditableValueHolder) component;
-				editable.setSubmittedValue(parameter);
-			}
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext,
-	 *      javax.faces.component.UIComponent)
-	 */
-	public void encodeBegin(FacesContext context, UIComponent component)
-			throws IOException {
-
-		super.encodeBegin(context, component);
-		Map attributes = component.getAttributes();
-		String moduleName;
-		String widgetName;
-		if (component instanceof GwtComponent) {
-			GwtComponent gwt = (GwtComponent) component;
-			moduleName = gwt.getModuleName();
-			widgetName = gwt.getWidgetName();
-		} else {
-			moduleName = (String) attributes.get("moduleName");
-			widgetName = (String) attributes.get("widgetName");
-		}
-		ResponseWriter writer = context.getResponseWriter();
-		// Write script and metas if not rendered before.
-		PageRenderer.writeModule(context, PageRenderer.getScriptBase(context), moduleName);
-		PageRenderer.writeScriptAndParameters(context);
-		// Base <span> - widget place
-		String element = getElement(component);
-		writer.startElement(element, component);
-		writer.writeAttribute("id", component.getClientId(context), null);
-		StringBuffer htmlClass = new StringBuffer(moduleName);
-		// GWT component module and widget name
-		if (null != widgetName) {
-			htmlClass.append(" ").append(widgetName);
-		}
-		Object styleClass = attributes.get("styleClass");
-		if (null != styleClass) {
-			htmlClass.append(" ").append(styleClass);
-		}
-		if (htmlClass.length() > 0) {
-			writer.writeAttribute("class", htmlClass, "styleClass");
-		}
-		Object style = attributes.get("style");
-		if (null != style) {
-			writer.writeAttribute("style", style, "style");
-		}
-		encodeFacets(writer, context, component, element);
-	}
-
-	/**
-	 * Hoock method for encode all component facets - use in subclass ability to
-	 * encode childrens and facets.
-	 * 
-	 * @param writer
-	 * @param context
-	 * @param component
-	 * @param element
-	 * @throws IOException
-	 */
-	protected void encodeFacets(ResponseWriter writer, FacesContext context,
-			UIComponent component, String element) throws IOException {
-		// Put content encoding here.
-	}
-
-	protected String getElement(UIComponent component) {
-		Object layout = component.getAttributes().get("layout");
-		return "block".equals(layout) ? "div" : "span";
-	}
-
-	/**
-	 * Write in html parameters to create widget. For {@link GwtComponent }
-	 * write html span element with id={@link UIComponent#getClientId(javax.faces.context.FacesContext)}+":_data"
-	 * and for each entry in {@link GwtComponent#getWidgetParameters()} map -
-	 * child span element, with title attribute from key , and text context with
-	 * value.
-	 * 
-	 * @param context
-	 * @param component
-	 * @throws IOException
-	 */
-	protected void writeWidgetParameters(FacesContext context,
-			UIComponent component) throws IOException {
-		// Write widget data.
-		Map widgetParameters = null;
-		if (component instanceof GwtComponent) {
-			GwtComponent gwt = (GwtComponent) component;
-			widgetParameters = gwt.getWidgetParameters();
-		}
-		String valueAsString = getValueAsString(context, component);
-		if (null != widgetParameters || null != valueAsString) {
-			ResponseWriter writer = context.getResponseWriter();
-			writer.startElement("span", component);
-			writer.writeAttribute("id", component.getClientId(context)
-					+ ":_data", null);
-			writer.writeAttribute("style", "display:none;", null);
-			if (null != widgetParameters) {
-				writeParametersMap(widgetParameters, writer);
-			}
-			writeParam(writer, "value", valueAsString);
-			writer.endElement("span");
-		}
-
-	}
-
-	/**
-	 * @param widgetParameters
-	 * @param writer
-	 * @throws IOException
-	 */
-	protected void writeParametersMap(Map widgetParameters,
-			ResponseWriter writer) throws IOException {
-		for (Iterator iter = widgetParameters.keySet().iterator(); iter
-				.hasNext();) {
-			Object key = iter.next();
-			Object paramValue = widgetParameters.get(key);
-			writeParam(writer, key, paramValue);
-		}
-	}
-
-	/**
-	 * @param writer
-	 * @param paramName
-	 * @param paramValue
-	 * @throws IOException
-	 */
-	protected void writeParam(ResponseWriter writer, Object paramName,
-			Object paramValue) throws IOException {
-		if (null != paramValue) {
-			// Write parameter
-			writer.startElement("span", null);
-			writer.writeAttribute("title", paramName, "param_name");
-			if (paramValue instanceof Map) {
-				Map paramMap = (Map) paramValue;
-				writeParametersMap(paramMap, writer);
-			} else {
-				writer.writeText(paramValue, "param_value");
-			}
-			writer.endElement("span");
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext,
-	 *      javax.faces.component.UIComponent)
-	 */
-	public void encodeEnd(FacesContext context, UIComponent component)
-			throws IOException {
-		// TODO Auto-generated method stub
-		super.encodeEnd(context, component);
-		String element = getElement(component);
-		ResponseWriter writer = context.getResponseWriter();
-		// Parameters
-		writeWidgetParameters(context, component);
-		// write state for append RPC calls parameter.
-		context.getApplication().getViewHandler().writeState(context);
-		// TODO - make serialization ?
-		writer.endElement(element);
-	}
-
-	/**
-	 * Return converted value for {@link javax.faces.component.ValueHolder} as
-	 * String, perform nessesary convertions.
-	 * 
-	 * @param context
-	 * @param component
-	 * @return
-	 */
-	public String getValueAsString(FacesContext context, UIComponent component) {
-		// First - get submitted value for input components
-		if (component instanceof EditableValueHolder) {
-			EditableValueHolder input = (EditableValueHolder) component;
-			String submittedValue = (String) input.getSubmittedValue();
-			if (null != submittedValue) {
-				return submittedValue;
-			}
-		}
-		// If no submitted value presented - convert same for UIInput/UIOutput
-		if (component instanceof ValueHolder) {
-			return formatValue(context, component, ((ValueHolder) component)
-					.getValue());
-		} else {
-			return null;
-		}
-	}
-
-	/**
-	 * Convert any object value to string. If component instance of
-	 * {@link ValueHolder } got {@link Converter} for formatting. If not,
-	 * attempt to use converter based on value type.
-	 * 
-	 * @param context
-	 * @param component
-	 * @return
-	 */
-	public String formatValue(FacesContext context, UIComponent component,
-			Object value) {
-		if (value instanceof String) {
-			return (String) value;
-		}
-		Converter converter = null;
-		if (component instanceof ValueHolder) {
-			ValueHolder holder = (ValueHolder) component;
-			converter = holder.getConverter();
-		}
-		if (null == converter && null != value) {
-			try {
-				converter = context.getApplication().createConverter(
-						value.getClass());
-			} catch (FacesException e) {
-				// TODO - log converter exception.
-			}
-		}
-		if (null != value) {
-			if (null == converter) {
-				return value.toString();
-			} else {
-				return converter.getAsString(context, component, value);
-			}
-		}
-		return null;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see javax.faces.render.Renderer#getConvertedValue(javax.faces.context.FacesContext,
-	 *      javax.faces.component.UIComponent, java.lang.Object)
-	 */
-	public Object getConvertedValue(FacesContext context,
-			UIComponent component, Object submittedValue)
-			throws ConverterException {
-		if (component instanceof EditableValueHolder) {
-			EditableValueHolder valueHolder = (EditableValueHolder) component;
-			return getConvertedUIInputValue(context, valueHolder,
-					(String) submittedValue);
-		}
-		return super.getConvertedValue(context, component, submittedValue);
-	}
-
-	public Object getConvertedUIInputValue(FacesContext facesContext,
-			EditableValueHolder component, String submittedValue)
-			throws ConverterException {
-
-		Object convertedValue = null;
-
-		/*
-		 * if (submittedValue == null) throw new
-		 * NullPointerException("submittedValue");
-		 */
-		if ("".equals(submittedValue)) {
-			return null;
-		}
-		Converter converter = getConverterForProperty(facesContext, component,
-				"value");
-		if (converter != null) {
-			convertedValue = converter.getAsObject(facesContext,
-					(UIComponent) component, submittedValue);
-		} else {
-			convertedValue = submittedValue;
-		}
-
-		return convertedValue;
-
-	}
-
-	/**
-	 * 
-	 * @param facesContext
-	 * @param component
-	 * @param property
-	 * @return converter for specified component attribute
-	 */
-	public Converter getConverterForProperty(FacesContext facesContext,
-			ValueHolder component, String property) {
-		Converter converter = component.getConverter();
-		if (converter == null) {
-			ValueExpression valueBinding = ((UIComponent) component)
-					.getValueExpression(property);
-			if (valueBinding != null) {
-				Class valueType = valueBinding.getType(facesContext
-						.getELContext());
-				if (String.class.equals(valueType)
-						|| Object.class.equals(valueType)) {
-					// No converter needed
-				} else {
-					converter = facesContext.getApplication().createConverter(
-							valueType);
-					if (converter == null) {
-						throw new ConverterException("No converter found for "
-								+ valueType.getName());
-					}
-				}
-			}
-		}
-		return converter;
-	}
-
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.jsf;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.el.ValueExpression;
+import javax.faces.FacesException;
+import javax.faces.component.ActionSource;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.ValueHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import javax.faces.render.Renderer;
+
+/**
+ * @author shura
+ * 
+ */
+public class WidgetRenderer extends Renderer {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext,
+	 *      javax.faces.component.UIComponent)
+	 */
+	public void decode(FacesContext context, UIComponent component) {
+		// TODO Auto-generated method stub
+		super.decode(context, component);
+		String clientId = component.getClientId(context);
+		Map requestParameterMap = context.getExternalContext()
+				.getRequestParameterMap();
+		Object parameter;
+		String paramName;
+		if (component instanceof ActionSource) {
+			if (component instanceof UIWidget) {
+				paramName = clientId + ((UIWidget) component).getActionParam();
+			} else {
+				paramName = clientId;
+			}
+			parameter = requestParameterMap.get(paramName);
+			if (null != parameter) {
+
+				// ActionSource action = (ActionSource) component;
+				component.queueEvent(new GwtActionEvent(component, parameter));
+			}
+		}
+		if (component instanceof EditableValueHolder) {
+			if (component instanceof UIWidget) {
+				paramName = clientId + ((UIWidget) component).getInputParam();
+			} else {
+				paramName = clientId;
+			}
+			parameter = requestParameterMap.get(paramName);
+			if (null != parameter) {
+				EditableValueHolder editable = (EditableValueHolder) component;
+				editable.setSubmittedValue(parameter);
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext,
+	 *      javax.faces.component.UIComponent)
+	 */
+	public void encodeBegin(FacesContext context, UIComponent component)
+			throws IOException {
+
+		super.encodeBegin(context, component);
+		Map attributes = component.getAttributes();
+		String moduleName;
+		String widgetName;
+		if (component instanceof GwtComponent) {
+			GwtComponent gwt = (GwtComponent) component;
+			moduleName = gwt.getModuleName();
+			widgetName = gwt.getWidgetName();
+		} else {
+			moduleName = (String) attributes.get("moduleName");
+			widgetName = (String) attributes.get("widgetName");
+		}
+		ResponseWriter writer = context.getResponseWriter();
+		// Write script and metas if not rendered before.
+		PageRenderer.writeModule(context, PageRenderer.getScriptBase(context), moduleName);
+		PageRenderer.writeParameters(context);
+		// Base <span> - widget place
+		String element = getElement(component);
+		writer.startElement(element, component);
+		writer.writeAttribute("id", component.getClientId(context), null);
+		StringBuffer htmlClass = new StringBuffer(moduleName);
+		// GWT component module and widget name
+		if (null != widgetName) {
+			htmlClass.append(" ").append(widgetName);
+		}
+		Object styleClass = attributes.get("styleClass");
+		if (null != styleClass) {
+			htmlClass.append(" ").append(styleClass);
+		}
+		if (htmlClass.length() > 0) {
+			writer.writeAttribute("class", htmlClass, "styleClass");
+		}
+		Object style = attributes.get("style");
+		if (null != style) {
+			writer.writeAttribute("style", style, "style");
+		}
+		encodeFacets(writer, context, component, element);
+	}
+
+	/**
+	 * Hoock method for encode all component facets - use in subclass ability to
+	 * encode childrens and facets.
+	 * 
+	 * @param writer
+	 * @param context
+	 * @param component
+	 * @param element
+	 * @throws IOException
+	 */
+	protected void encodeFacets(ResponseWriter writer, FacesContext context,
+			UIComponent component, String element) throws IOException {
+		// Put content encoding here.
+	}
+
+	protected String getElement(UIComponent component) {
+		Object layout = component.getAttributes().get("layout");
+		return "block".equals(layout) ? "div" : "span";
+	}
+
+	/**
+	 * Write in html parameters to create widget. For {@link GwtComponent }
+	 * write html span element with id={@link UIComponent#getClientId(javax.faces.context.FacesContext)}+":_data"
+	 * and for each entry in {@link GwtComponent#getWidgetParameters()} map -
+	 * child span element, with title attribute from key , and text context with
+	 * value.
+	 * 
+	 * @param context
+	 * @param component
+	 * @throws IOException
+	 */
+	protected void writeWidgetParameters(FacesContext context,
+			UIComponent component) throws IOException {
+		// Write widget data.
+		Map widgetParameters = null;
+		if (component instanceof GwtComponent) {
+			GwtComponent gwt = (GwtComponent) component;
+			widgetParameters = gwt.getWidgetParameters();
+		}
+		String valueAsString = getValueAsString(context, component);
+		if (null != widgetParameters || null != valueAsString) {
+			ResponseWriter writer = context.getResponseWriter();
+			writer.startElement("span", component);
+			writer.writeAttribute("id", component.getClientId(context)
+					+ ":_data", null);
+			writer.writeAttribute("style", "display:none;", null);
+			if (null != widgetParameters) {
+				writeParametersMap(widgetParameters, writer);
+			}
+			writeParam(writer, "value", valueAsString);
+			writer.endElement("span");
+		}
+
+	}
+
+	/**
+	 * @param widgetParameters
+	 * @param writer
+	 * @throws IOException
+	 */
+	protected void writeParametersMap(Map widgetParameters,
+			ResponseWriter writer) throws IOException {
+		for (Iterator iter = widgetParameters.keySet().iterator(); iter
+				.hasNext();) {
+			Object key = iter.next();
+			Object paramValue = widgetParameters.get(key);
+			writeParam(writer, key, paramValue);
+		}
+	}
+
+	/**
+	 * @param writer
+	 * @param paramName
+	 * @param paramValue
+	 * @throws IOException
+	 */
+	protected void writeParam(ResponseWriter writer, Object paramName,
+			Object paramValue) throws IOException {
+		if (null != paramValue) {
+			// Write parameter
+			writer.startElement("span", null);
+			writer.writeAttribute("title", paramName, "param_name");
+			if (paramValue instanceof Map) {
+				Map paramMap = (Map) paramValue;
+				writeParametersMap(paramMap, writer);
+			} else {
+				writer.writeText(paramValue, "param_value");
+			}
+			writer.endElement("span");
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext,
+	 *      javax.faces.component.UIComponent)
+	 */
+	public void encodeEnd(FacesContext context, UIComponent component)
+			throws IOException {
+		// TODO Auto-generated method stub
+		super.encodeEnd(context, component);
+		String element = getElement(component);
+		ResponseWriter writer = context.getResponseWriter();
+		// Parameters
+		writeWidgetParameters(context, component);
+		// write state for append RPC calls parameter.
+		context.getApplication().getViewHandler().writeState(context);
+		// TODO - make serialization ?
+		writer.endElement(element);
+	}
+
+	/**
+	 * Return converted value for {@link javax.faces.component.ValueHolder} as
+	 * String, perform nessesary convertions.
+	 * 
+	 * @param context
+	 * @param component
+	 * @return
+	 */
+	public String getValueAsString(FacesContext context, UIComponent component) {
+		// First - get submitted value for input components
+		if (component instanceof EditableValueHolder) {
+			EditableValueHolder input = (EditableValueHolder) component;
+			String submittedValue = (String) input.getSubmittedValue();
+			if (null != submittedValue) {
+				return submittedValue;
+			}
+		}
+		// If no submitted value presented - convert same for UIInput/UIOutput
+		if (component instanceof ValueHolder) {
+			return formatValue(context, component, ((ValueHolder) component)
+					.getValue());
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * Convert any object value to string. If component instance of
+	 * {@link ValueHolder } got {@link Converter} for formatting. If not,
+	 * attempt to use converter based on value type.
+	 * 
+	 * @param context
+	 * @param component
+	 * @return
+	 */
+	public String formatValue(FacesContext context, UIComponent component,
+			Object value) {
+		if (value instanceof String) {
+			return (String) value;
+		}
+		Converter converter = null;
+		if (component instanceof ValueHolder) {
+			ValueHolder holder = (ValueHolder) component;
+			converter = holder.getConverter();
+		}
+		if (null == converter && null != value) {
+			try {
+				converter = context.getApplication().createConverter(
+						value.getClass());
+			} catch (FacesException e) {
+				// TODO - log converter exception.
+			}
+		}
+		if (null != value) {
+			if (null == converter) {
+				return value.toString();
+			} else {
+				return converter.getAsString(context, component, value);
+			}
+		}
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.faces.render.Renderer#getConvertedValue(javax.faces.context.FacesContext,
+	 *      javax.faces.component.UIComponent, java.lang.Object)
+	 */
+	public Object getConvertedValue(FacesContext context,
+			UIComponent component, Object submittedValue)
+			throws ConverterException {
+		if (component instanceof EditableValueHolder) {
+			EditableValueHolder valueHolder = (EditableValueHolder) component;
+			return getConvertedUIInputValue(context, valueHolder,
+					(String) submittedValue);
+		}
+		return super.getConvertedValue(context, component, submittedValue);
+	}
+
+	public Object getConvertedUIInputValue(FacesContext facesContext,
+			EditableValueHolder component, String submittedValue)
+			throws ConverterException {
+
+		Object convertedValue = null;
+
+		/*
+		 * if (submittedValue == null) throw new
+		 * NullPointerException("submittedValue");
+		 */
+		if ("".equals(submittedValue)) {
+			return null;
+		}
+		Converter converter = getConverterForProperty(facesContext, component,
+				"value");
+		if (converter != null) {
+			convertedValue = converter.getAsObject(facesContext,
+					(UIComponent) component, submittedValue);
+		} else {
+			convertedValue = submittedValue;
+		}
+
+		return convertedValue;
+
+	}
+
+	/**
+	 * 
+	 * @param facesContext
+	 * @param component
+	 * @param property
+	 * @return converter for specified component attribute
+	 */
+	public Converter getConverterForProperty(FacesContext facesContext,
+			ValueHolder component, String property) {
+		Converter converter = component.getConverter();
+		if (converter == null) {
+			ValueExpression valueBinding = ((UIComponent) component)
+					.getValueExpression(property);
+			if (valueBinding != null) {
+				Class valueType = valueBinding.getType(facesContext
+						.getELContext());
+				if (String.class.equals(valueType)
+						|| Object.class.equals(valueType)) {
+					// No converter needed
+				} else {
+					converter = facesContext.getApplication().createConverter(
+							valueType);
+					if (converter == null) {
+						throw new ConverterException("No converter found for "
+								+ valueType.getName());
+					}
+				}
+			}
+		}
+		return converter;
+	}
+
+}

Modified: trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/server/GwtFacesServlet.java
===================================================================
--- trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/server/GwtFacesServlet.java	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/java/org/ajax4jsf/gwt/server/GwtFacesServlet.java	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,191 +1,171 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
- */
-
-package org.ajax4jsf.gwt.server;
-
-import java.lang.reflect.Method;
-import java.util.Enumeration;
-
-import javax.faces.component.ContextCallback;
-import javax.faces.component.UIComponent;
-import javax.faces.context.FacesContext;
-import javax.faces.event.PhaseListener;
-import javax.faces.lifecycle.Lifecycle;
-import javax.servlet.http.HttpServletRequest;
-
-import org.ajax4jsf.gwt.client.ComponentEntryPoint;
-import org.ajax4jsf.gwt.client.GwtFacesEvent;
-import org.ajax4jsf.gwt.client.GwtFacesException;
-import org.ajax4jsf.gwt.client.GwtFacesResult;
-import org.ajax4jsf.gwt.client.GwtFacesService;
-import org.ajax4jsf.gwt.jsf.GwtComponent;
-import org.ajax4jsf.gwt.jsf.GwtCallListener;
-import org.ajax4jsf.gwt.jsf.GwtEvent;
-import org.ajax4jsf.gwt.jsf.GwtListener;
-import org.ajax4jsf.gwt.jsf.GwtSource;
-
-import com.google.gwt.user.server.rpc.RemoteServiceServlet;
-
-/**
- * @author shura
- * 
- */
-public class GwtFacesServlet extends RemoteServiceServlet implements
-		GwtFacesService {
-
-	protected Lifecycle lifecycle;
-	
-	private static final Class[] CALL_PARAMS = {GwtFacesEvent.class};
-
-
-	/* (non-Javadoc)
-	 * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
-	 */
-//	public void init(ServletConfig config) throws ServletException {
-//		super.init(config);
-//		try {
-//			LifecycleFactory factory;
-//			factory = (LifecycleFactory) FactoryFinder
-//					.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
-//			lifecycle = factory
-//					.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
-//		} catch (Exception e) {
-//			 
-//		}
-//	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.ajax4jsf.gwt.sample.client.GwtFacesService#sendEvent(org.ajax4jsf.gwt.sample.client.GwtFacesEvent)
-	 */
-	public GwtFacesResult sendEvent(final GwtFacesEvent event)
-			throws GwtFacesException {
-		FacesContext facesContext = FacesContext.getCurrentInstance();
-		String clientId ;
-		GwtFacesResult gwtFacesResult = null;
-		if (null != facesContext) {
-			clientId = (String) facesContext.getExternalContext().getRequestParameterMap().get("clientId");
-			if (null != clientId) {
-				// Invoke event on target component
-				GwtFacesCallback callback = new GwtFacesCallback(event);
-				try {
-					facesContext.getViewRoot().invokeOnComponent(facesContext,
-							clientId, callback);
-				} catch (Exception e) {
-					throw new GwtFacesException(
-							"Error send event to component: " + e.getMessage());
-				}
-				gwtFacesResult = callback.getGwtFacesResult();
-			} else if(null != lifecycle){
-				// Invoke event on registered listeners.
-				PhaseListener[] listeners = lifecycle.getPhaseListeners();
-				for (int i = 0; i < listeners.length; i++) {
-					PhaseListener listener = listeners[i];
-					if (listener instanceof GwtCallListener) {
-						GwtCallListener gwtListener = (GwtCallListener) listener;
-						gwtFacesResult = gwtListener.processGwtEvent(event);
-					}
-				}
-			}
-		} else {
-			// Non-faces environment, attempt to load stub class for hosted mode
-			try {
-				HttpServletRequest threadLocalRequest = getThreadLocalRequest();
-				String moduleName = threadLocalRequest.getParameter(ComponentEntryPoint.GWT_MODULE_NAME_PARAMETER);
-				if(null == moduleName){
-					throw new GwtFacesException("Module name not set in request");
-				}
-				// Find latest package delimiter. GWT not allow to use default package - since
-				// always present.
-				int i = moduleName.lastIndexOf('.');
-				// Module class name
-				String className = "Mock" + moduleName.substring(i+1);
-				// Module package name
-				String packageName = moduleName.substring(0,i)+".server.";
-				ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-				className = packageName+className;
-				Class clazz = classLoader.loadClass(className);
-				GwtFacesService service = (GwtFacesService) clazz.newInstance();
-				gwtFacesResult = service.sendEvent(event);
-			} catch (Exception e) {
-				// TODO Auto-generated catch block
-				throw new GwtFacesException("Error to call test method"+e.getMessage());
-			}
-		}
-		return gwtFacesResult;
-	}
-
-	private static class GwtFacesCallback implements ContextCallback {
-		private GwtFacesResult gwtFacesResult = null;
-
-		private GwtFacesEvent event;
-
-		/**
-		 * @param event
-		 */
-		public GwtFacesCallback(GwtFacesEvent event) {
-			super();
-			// TODO Auto-generated constructor stub
-			this.event = event;
-		}
-
-		public void invokeContextCallback(FacesContext context,
-				UIComponent target) {
-			if (target instanceof GwtSource) {
-				GwtEvent gwtEvent = new GwtEvent(target){
-
-					public GwtFacesResult getCallbackParameter() {
-						// TODO Auto-generated method stub
-						return gwtFacesResult;
-					}
-
-					public void setCallbackParameter(GwtFacesResult callbackParam) {
-						gwtFacesResult = callbackParam;
-						
-					}
-
-					public GwtFacesEvent getGwtEventData() {
-						// TODO Auto-generated method stub
-						return event;
-					}
-					
-				};
-				target.broadcast(gwtEvent);
-			}
-			if (target instanceof GwtListener) {
-				GwtListener listener = (GwtListener) target;
-				if(listener.isAcceptEvent(event)){
-					gwtFacesResult = listener.processEvent(event);
-				}
-			}
-
-		}
-
-		/**
-		 * @return Returns the gwtFacesResult.
-		 */
-		public GwtFacesResult getGwtFacesResult() {
-			return gwtFacesResult;
-		}
-
-	}
-}
+/**
+ * 
+ */
+package org.ajax4jsf.gwt.server;
+
+import javax.faces.component.ContextCallback;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseListener;
+import javax.faces.lifecycle.Lifecycle;
+import javax.servlet.http.HttpServletRequest;
+
+import org.ajax4jsf.gwt.client.ComponentEntryPoint;
+import org.ajax4jsf.gwt.client.GwtFacesEvent;
+import org.ajax4jsf.gwt.client.GwtFacesService;
+import org.ajax4jsf.gwt.jsf.GwtCallListener;
+import org.ajax4jsf.gwt.jsf.GwtEvent;
+import org.ajax4jsf.gwt.jsf.GwtListener;
+import org.ajax4jsf.gwt.jsf.GwtSource;
+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
+import com.google.gwt.user.server.rpc.UnexpectedException;
+import com.google.gwt.user.server.rpc.RPCRequest;
+import com.google.gwt.user.server.rpc.RPC;
+import com.google.gwt.user.client.rpc.SerializationException;
+
+/**
+ * @author shura
+ * 
+ */
+public class GwtFacesServlet extends RemoteServiceServlet {
+
+    protected Lifecycle lifecycle;
+
+    private static final Class[] CALL_PARAMS = {GwtFacesEvent.class};
+
+
+    /**
+     * Handle the GWT RPC call by looking up the client ID specified in the request, and passing a callback
+     * via JSF to the proper JSF component.
+     */
+    public String processCall (String requestPayload)
+        throws SerializationException {
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+        String clientId;
+        String responsePayload = null;
+        RPCRequest rpcRequest;
+        rpcRequest = RPC.decodeRequest(requestPayload);
+
+        if (null != facesContext) {
+            clientId = (String)facesContext.getExternalContext().getRequestParameterMap().get("clientId");
+
+            if (null != clientId) {
+
+                // Invoke event on target component
+                GwtFacesCallback callback = new GwtFacesCallback(rpcRequest);
+                try {
+                    facesContext.getViewRoot().invokeOnComponent(facesContext,
+                            clientId, callback);
+                } catch (Exception e) {
+                    // Hmm, for now, let's make this be a server-only exception.
+                    throw new UnexpectedException("Error send event to component", e);
+                }
+                responsePayload = callback.getResponsePayload();
+            } else if(null != lifecycle){
+                // Invoke event on registered listeners.
+                PhaseListener[] listeners = lifecycle.getPhaseListeners();
+                for (int i = 0; i < listeners.length; i++) {
+                    PhaseListener listener = listeners[i];
+                    if (listener instanceof GwtCallListener) {
+                        GwtCallListener gwtListener = (GwtCallListener) listener;
+                        responsePayload = gwtListener.processRequest(rpcRequest);
+                    }
+                }
+            }
+        } else {
+            // Non-faces environment, attempt to load stub class for hosted mode
+            HttpServletRequest threadLocalRequest = getThreadLocalRequest();
+            String moduleName = threadLocalRequest.getParameter(ComponentEntryPoint.GWT_MODULE_NAME_PARAMETER);
+            if(null == moduleName){
+                // Hackish here, not sure this will work properly.....
+                throw new SecurityException("Module name not set in request");
+            }
+            // Find latest package delimiter. GWT not allow to use default package - since
+            // always present.
+            int i = moduleName.lastIndexOf('.');
+            // Module class name
+            String className = "Mock" + moduleName.substring(i+1);
+            // Module package name
+            String packageName = moduleName.substring(0,i)+".server.";
+            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+            className = packageName+className;
+            Class clazz = null;
+            try {
+                clazz = classLoader.loadClass(className);
+
+                // assume it's looking for GwtFacesService.
+                // TODO: figure out how to tell what it's actually looking for!
+                // (probably just trust the call!?!)
+                GwtFacesService service = (GwtFacesService) clazz.newInstance();
+                // OK so it warns about varargs redundancy here, but what does it want????
+                responsePayload = RPC.invokeAndEncodeResponse(service, rpcRequest.getMethod(), rpcRequest.getParameters());
+            } catch (ClassNotFoundException e) {
+                throw new SecurityException("Could not find requested mock class " + className);
+            } catch (Exception e) {
+                throw new SecurityException("Could not construct mock service class " + clazz);
+            }
+        }
+        return responsePayload;
+    }
+
+    /**
+     * This callback object is passed to ViewRoot.invokeOnComponent() to invoke the RPCCall
+     * on the proper JSF component.
+     */
+    private static class GwtFacesCallback implements ContextCallback {
+        private String responsePayload = null;
+
+        private RPCRequest request;
+
+        /**
+         * Construct a callback for the specified call.
+         */
+        public GwtFacesCallback(RPCRequest request) {
+            super();
+            this.request = request;
+        }
+
+        /**
+         * Called by JSF to invoke the call on the specified target.
+         * @param context
+         * @param target
+         */
+        public void invokeContextCallback(FacesContext context,
+                                          UIComponent target) {
+            if (target instanceof GwtSource) {
+                GwtEvent gwtEvent = new GwtEvent(target){
+
+                    public String getResponsePayload() {
+                        // TODO Auto-generated method stub
+                        return responsePayload;
+                    }
+
+                    public void setCallbackParameter(String callbackParam) {
+                        responsePayload = callbackParam;
+
+                    }
+
+                    public RPCRequest getRPCRequest () {
+                        // TODO Auto-generated method stub
+                        return request;
+                    }
+
+                };
+                target.broadcast(gwtEvent);
+            }
+            if (target instanceof GwtListener) {
+                GwtListener listener = (GwtListener) target;
+                responsePayload = listener.processRequest(request);
+            }
+
+        }
+
+        /**
+         * @return Returns the gwtFacesResult.
+         */
+        public String getResponsePayload() {
+            return responsePayload;
+        }
+
+    }
+}

Modified: trunk/gwtjsf/src/main/resources/META-INF/faces-config.xml
===================================================================
--- trunk/gwtjsf/src/main/resources/META-INF/faces-config.xml	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/resources/META-INF/faces-config.xml	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,33 +1,37 @@
-<?xml version="1.0"?>
-<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
- <component>
-  <component-type>org.ajax4jsf.gwt.Page</component-type>
-  <component-class>org.ajax4jsf.gwt.jsf.UIPage</component-class>
- </component>
- <component>
-  <component-type>org.ajax4jsf.gwt.Widget</component-type>
-  <component-class>org.ajax4jsf.gwt.jsf.UIWidget</component-class>
- </component>
- <render-kit>
-  <renderer>
-   <component-family>org.ajax4jsf.gwt.Widget</component-family>
-   <renderer-type>org.ajax4jsf.gwt.Widget</renderer-type>
-   <renderer-class>org.ajax4jsf.gwt.jsf.WidgetRenderer</renderer-class>
-  </renderer>
-  <renderer>
-   <component-family>org.ajax4jsf.gwt.Widget</component-family>
-   <renderer-type>org.ajax4jsf.gwt.WidgetWithFacets</renderer-type>
-   <renderer-class>org.ajax4jsf.gwt.jsf.WidgetWithFacetsRenderer</renderer-class>
-  </renderer>
-  <renderer>
-   <component-family>org.ajax4jsf.gwt.Page</component-family>
-   <renderer-type>org.ajax4jsf.gwt.Page</renderer-type>
-   <renderer-class>org.ajax4jsf.gwt.jsf.PageRenderer</renderer-class>
-  </renderer>
- </render-kit>
- <lifecycle>
-  <phase-listener>org.ajax4jsf.gwt.jsf.GwtPhaseListener</phase-listener>
- </lifecycle>
-</faces-config>
+<?xml version="1.0"?>
+<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
+              xmlns:xi="http://www.w3.org/2001/XInclude"
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
+    <component>
+        <component-type>org.ajax4jsf.gwt.Page</component-type>
+        <component-class>org.ajax4jsf.gwt.jsf.UIPage</component-class>
+    </component>
+    <component>
+        <component-type>org.ajax4jsf.gwt.Widget</component-type>
+        <component-class>org.ajax4jsf.gwt.jsf.UIWidget</component-class>
+    </component>
+    <render-kit>
+        <renderer>
+            <component-family>org.ajax4jsf.gwt.Widget</component-family>
+            <renderer-type>org.ajax4jsf.gwt.Widget</renderer-type>
+            <renderer-class>org.ajax4jsf.gwt.jsf.WidgetRenderer</renderer-class>
+        </renderer>
+        <renderer>
+            <component-family>org.ajax4jsf.gwt.Widget</component-family>
+            <renderer-type>org.ajax4jsf.gwt.WidgetWithFacets</renderer-type>
+            <renderer-class>org.ajax4jsf.gwt.jsf.WidgetWithFacetsRenderer</renderer-class>
+        </renderer>
+        <renderer>
+            <component-family>org.ajax4jsf.gwt.Page</component-family>
+            <renderer-type>org.ajax4jsf.gwt.Page</renderer-type>
+            <renderer-class>org.ajax4jsf.gwt.jsf.PageRenderer</renderer-class>
+        </renderer>
+    </render-kit>
+    <!-- commented out as per Jason DeTiberus -->
+    <!-- All plain G4JSF apps MUST add this in themselves -->
+    <!--
+    <lifecycle>
+     <phase-listener>org.ajax4jsf.gwt.jsf.GwtPhaseListener</phase-listener>
+    </lifecycle>
+    -->
+</faces-config>

Deleted: trunk/gwtjsf/src/main/resources/META-INF/gwt/gwt.js
===================================================================
--- trunk/gwtjsf/src/main/resources/META-INF/gwt/gwt.js	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/gwtjsf/src/main/resources/META-INF/gwt/gwt.js	2007-06-22 07:53:56 UTC (rev 274)
@@ -1,1156 +0,0 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
-
-// This startup script should be included in host pages either just after
-
-// <body> or inside the <head> after module <meta> tags.
-
-//
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-
-// DynamicResources
-
-//
-
-
-
-function DynamicResources() {
-
-  this.pendingElemsBySrc_ = {};
-
-  this.pendingScriptElems_ = new Array();
-
-}
-
-DynamicResources.prototype = {};
-
-
-
-// The array is set up such that, pairwise, the entries are (src, readyFnStr).
-
-// Called once for each module that is attached to the host page.
-
-// It is theoretically possible that addScripts() could be called reentrantly
-
-// if the browser event loop is pumped during this function and an iframe loads; 
-
-// we may want to enhance this method in the future to support that case.
-
-DynamicResources.prototype.addScripts = function(scriptArray, insertBeforeElem) {
-
-  var wasEmpty = (this.pendingScriptElems_.length == 0);
-
-  var anyAdded = false;
-
-  for (var i = 0, n = scriptArray.length; i < n; i += 2) {
-
-    var src = scriptArray[i];
-
-    if (this.pendingElemsBySrc_[src]) {
-
-      // Don't load the same script twice.
-
-      continue;
-
-    }
-
-    // Set up the element but don't add it to the DOM until its turn.
-
-    anyAdded = true;
-
-    var e = document.createElement("script");
-
-    this.pendingElemsBySrc_[src] = e;
-
-    var readyFn;
-
-    eval("readyFn = " + scriptArray[i+1]);
-
-    e.__readyFn = readyFn;
-
-    e.type = "text/javascript";
-
-    e.src = src;
-
-    e.__insertBeforeElem = insertBeforeElem;
-
-    this.pendingScriptElems_ = this.pendingScriptElems_.concat(e);
-
-  }
-
-  
-
-  if (wasEmpty && anyAdded) {
-
-    // Kickstart.
-
-    this.injectScript(this.pendingScriptElems_[0]);
-
-  }
-
-}
-
-
-
-DynamicResources.prototype.injectScript = function(scriptElem) {
-
-  var parentElem = scriptElem.__insertBeforeElem.parentNode;
-
-  parentElem.insertBefore(scriptElem, scriptElem.__insertBeforeElem);
-
-}
-
-
-
-DynamicResources.prototype.addStyles = function(styleSrcArray, insertBeforeElem) {
-
-  var parent = insertBeforeElem.parentNode;
-
-  for (var i = 0, n = styleSrcArray.length; i < n; ++i) {
-
-    var src = styleSrcArray[i];
-
-    if (this.pendingElemsBySrc_[src]) 
-
-      continue;
-
-    var e = document.createElement("link");
-
-    this.pendingElemsBySrc_[src] = e;
-
-    e.type = "text/css";
-
-    e.rel = "stylesheet";
-
-    e.href = src;
-
-    parent.insertBefore(e, insertBeforeElem);
-
-  }
-
-}
-
-
-
-DynamicResources.prototype.isReady = function() {
-
-  var elems = this.pendingScriptElems_;
-
-  if (elems.length > 0) {
-
-    var e = elems[0];
-
-    if (!e.__readyFn()) {
-
-      // The pending script isn't ready yet.
-
-      return false;
-
-    }
-
-    
-
-    // The pending script has now finished loading. Enqueue the next, if any.
-
-    e.__readyFn = null;
-
-    elems.shift();
-
-    if (elems.length > 0) {
-
-      // There is another script.
-
-      this.injectScript(elems[0]);
-
-      return false;
-
-    }
-
-  }
-
-
-
-  // There are no more pending scripts.
-
-  return true;
-
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-
-// ModuleControlBlock
-
-//
-
-function ModuleControlBlock(metaElem, rawName) {
-
-  var parts = ["", rawName];
-
-  var i = rawName.lastIndexOf("=");
-
-  if (i != -1) {
-
-    parts[0] = rawName.substring(0, i) + '/';
-
-    parts[1] = rawName.substring(i+1);
-
-  }
-
-
-
-  this.metaElem_ = metaElem;
-
-  this.baseUrl_ = parts[0];
-
-  this.name_ = parts[1];
-
-  this.compilationLoaded_ = false;
-
-  this.frameWnd_ = null;
-
-}
-
-ModuleControlBlock.prototype = {};
-
-
-
-/**
-
- * Determines whether this module is fully loaded and ready to run.
-
- */
-
-ModuleControlBlock.prototype.isReady = function() {
-
-  return this.compilationLoaded_;
-
-};
-
-
-
-/**
-
- * Called when the compilation for this module is loaded.
-
- */
-
-ModuleControlBlock.prototype.compilationLoaded = function(frameWnd) {
-
-  this.frameWnd_ = frameWnd;
-
-  this.compilationLoaded_ = true;
-
-}
-
-
-
-/**
-
- * Gets the logical module name, not including a base url prefix if one was
-
- * specified.
-
- */
-
-ModuleControlBlock.prototype.getName = function() {
-
-  return this.name_;
-
-}
-
-
-
-/**
-
- * Gets the base URL of the module, guaranteed to end with a slash.
-
- */
-
-ModuleControlBlock.prototype.getBaseURL = function() {
-
-  return this.baseUrl_;
-
-}
-
-
-
-/**
-
- * Gets the window of the module's frame.
-
- */
-
-ModuleControlBlock.prototype.getModuleFrameWindow = function() {
-
-  return this.frameWnd_;
-
-}
-
-
-
-/**
-
- * Injects a set of dynamic scripts.
-
- * The array is set up such that, pairwise, the entries are (src, readyFnStr).
-
- */
-
-ModuleControlBlock.prototype.addScripts = function(scriptSrcArray) {
-
-  return ModuleControlBlocks.dynamicResources_.addScripts(scriptSrcArray, this.metaElem_);
-
-}
-
-
-
-/**
-
- * Injects a set of dynamic styles.
-
- */
-
-ModuleControlBlock.prototype.addStyles = function(styleSrcArray) {
-
-  return ModuleControlBlocks.dynamicResources_.addStyles(styleSrcArray, this.metaElem_);
-
-}
-
- 
-
-//////////////////////////////////////////////////////////////////////////////
-
-// ModuleControlBlocks
-
-//
-
-function ModuleControlBlocks() {
-
-  this.blocks_ = [];
-
-}
-
-ModuleControlBlocks.dynamicResources_ = new DynamicResources(); // "static"
-
-ModuleControlBlocks.prototype = {};
-
-
-
-/**
-
- * Adds a module control control block for the named module.
-
- * @param metaElem the meta element that caused the module to be added
-
- * @param name the name of the module being added, optionally preceded by
-
- * an alternate base url of the form "_path_=_module_".
-
- */
-
-ModuleControlBlocks.prototype.add = function(metaElem, name) {
-
-  var mcb = new ModuleControlBlock(metaElem, name);
-
-  this.blocks_ = this.blocks_.concat(mcb);
-
-};
-
-
-
-/**
-
- * Determines whether all the modules are loaded and ready to run.
-
- */
-
-ModuleControlBlocks.prototype.isReady = function() {
-
-  for (var i = 0, n = this.blocks_.length; i < n; ++i) {
-
-    var mcb = this.blocks_[i];
-
-    if (!mcb.isReady()) {
-
-      return false;
-
-    }
-
-  }
-
-  
-
-  // Are there any pending dynamic resources (e.g. styles, scripts)?
-
-  if (!ModuleControlBlocks.dynamicResources_.isReady()) {
-
-    // No, we're still waiting on one or more dynamic resources.
-
-    return false;
-
-  }
-
-
-
-  return true;
-
-}
-
-
-
-/**
-
- * Determines whether there are any module control blocks.
-
- */
-
-ModuleControlBlocks.prototype.isEmpty = function() {
-
-  return this.blocks_.length == 0;
-
-}
-
-
-
-/**
-
- * Gets the module control block at the specified index.
-
- */
-
-ModuleControlBlocks.prototype.get = function(index) {
-
-  return this.blocks_[index];
-
-}
-
-
-
-/**
-
- * Injects an iframe for each module.
-
- */
-
-ModuleControlBlocks.prototype.injectFrames = function() {
-
-  for (var i = 0, n = this.blocks_.length; i < n; ++i) {
-
-    var mcb = this.blocks_[i];
-
-
-
-    // Insert an iframe for the module
-
-    var iframe = document.createElement("iframe");
-
-    var selectorUrl = mcb.getBaseURL() + mcb.getName() + ".nocache.html";
-
-    selectorUrl += "?" + (__gwt_isHosted() ? "h&" : "" ) + i;
-
-    var unique = new Date().getTime();
-
-    selectorUrl += "&" + unique;
-
-    iframe.style.border = '0px';
-
-    iframe.style.width = '0px';
-
-    iframe.style.height = '0px';
-
-    
-
-    // Fragile browser-specific ordering issues below
-
-    
-
-/*@cc_on
-
-    // prevent extra clicky noises on IE
-
-    iframe.src = selectorUrl;
-
-@*/
-
-    
-
-    if (document.body.firstChild) {
-
-      document.body.insertBefore(iframe, document.body.firstChild);
-
-    } else {
-
-      document.body.appendChild(iframe);
-
-    }
-
-    
-
-/*@cc_on
-
-    // prevent extra clicky noises on IE
-
-    return;
-
-@*/
-
-
-
-    if (iframe.contentWindow) {
-
-      // Older Mozilla has a caching bug for the iframe and won't reload the nocache.
-
-      iframe.contentWindow.location.replace(selectorUrl);
-
-    } else {
-
-      // Older Safari doesn't have a contentWindow.
-
-      iframe.src = selectorUrl;
-
-    }
-
-  }
-
-}
-
-
-
-/**
-
- * Runs the entry point for each module.
-
- */
-
-ModuleControlBlocks.prototype.run = function() {
-
-  for (var i = 0, n = this.blocks_.length; i < n; ++i) {
-
-    var mcb = this.blocks_[i];
-
-    var name = mcb.getName();
-
-    var frameWnd = mcb.getModuleFrameWindow();
-
-    if (__gwt_isHosted()) {
-
-      if (!window.external.gwtOnLoad(frameWnd, name)) {
-
-        // Module failed to load.
-
-        if (__gwt_onLoadError) {
-
-            __gwt_onLoadError(name);
-
-        } else {
-
-            window.alert("Failed to load module '" + name + 
-
-            "'.\nPlease see the log in the development shell for details.");
-
-        }
-
-      }
-
-    } else {
-
-      // The compilation itself handles calling the error function.
-
-      frameWnd.gwtOnLoad(__gwt_onLoadError, name);
-
-    }
-
-  }
-
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-
-// Globals
-
-//
-
-
-
-var __gwt_retryWaitMillis = 10;
-
-var __gwt_isHostPageLoaded = false;
-
-var __gwt_metaProps = {};
-
-var __gwt_onPropertyError = null;
-
-var __gwt_onLoadError = null;
-
-var __gwt_moduleControlBlocks = new ModuleControlBlocks();
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-
-// Common 
-
-//
-
-
-
-/**
-
- * Determines whether or not the page is being loaded in the GWT hosted browser.
-
- */
-
-function __gwt_isHosted() {
-
-  if (window.external && window.external.gwtOnLoad) {
-
-    // gwt.hybrid makes the hosted browser pretend not to be
-
-    if (document.location.href.indexOf("gwt.hybrid") == -1) {
-
-      return true;
-
-    }
-
-  }
-
-  return false;
-
-}
-
-
-
-/**
-
- * Tries to get a module control block based on a query string passed in from
-
- * the caller. Used by iframes to get references back to their mcbs.
-
- * @param queryString the entire query string as returned by location.search,
-
- * which notably includes the leading '?' if one is specified
-
- * @return the relevant module control block, or <code>null</code> if it cannot 
-
- * be derived based on <code>queryString</code>
-
- */
-
-function __gwt_tryGetModuleControlBlock(queryString) {
-
-  if (queryString.length > 0) {
-
-    // The pattern is ?[h&]<index>[&<unique>]
-
-    var queryString = queryString.substring(1);
-
-    if (queryString.indexOf("h&") == 0) {
-
-      // Ignore the hosted mode flag here; only GWTShellServlet cares about it.
-
-      queryString = queryString.substring(2);
-
-    }
-
-    var pos = queryString.indexOf("&");
-
-    if (pos >= 0) {
-
-      queryString = queryString.substring(0, pos);
-
-    }
-
-    var mcbIndex = parseInt(queryString);
-
-    if (!isNaN(mcbIndex)) {
-
-      var mcb = __gwt_moduleControlBlocks.get(mcbIndex);
-
-      return mcb;
-
-    }
-
-    // Ignore the unique number that remains on the query string.
-
-  }
-
-  return null;
-
-}
-
-
-
-/**
-
- * Parses meta tags from the host html.
-
- * 
-
- * <meta name="gwt:module" content="_module-name_">
-
- *    causes the specified module to be loaded
-
- *
-
- * <meta name="gwt:property" content="_name_=_value_">
-
- *    statically defines a deferred binding client property
-
- *
-
- * <meta name="gwt:onPropertyErrorFn" content="_fnName_">
-
- *    specifies the name of a function to call if a client property is set to 
-
- *    an invalid value (meaning that no matching compilation will be found)
-
- * 
-
- * <meta name="gwt:onLoadErrorFn" content="_fnName_">
-
- *    specifies the name of a function to call if an exception happens during 
-
- *    bootstrapping or if a module throws an exception out of onModuleLoad(); 
-
- *    the function should take a message parameter
-
- */
-
-function __gwt_processMetas() {
-
-  var metas = document.getElementsByTagName("meta");
-
-  for (var i = 0, n = metas.length; i < n; ++i) {
-
-    var meta = metas[i];
-
-    var name = meta.getAttribute("name");
-
-    if (name) {
-
-      if (name == "gwt:module") {
-
-        var moduleName = meta.getAttribute("content");
-
-        if (moduleName) {
-
-          __gwt_moduleControlBlocks.add(meta, moduleName);
-
-        }
-
-      } else if (name == "gwt:property") {
-
-        var content = meta.getAttribute("content");
-
-        if (content) {
-
-          var name = content, value = "";
-
-          var eq = content.indexOf("=");
-
-          if (eq != -1) {
-
-            name = content.substring(0, eq);
-
-            value = content.substring(eq+1);
-
-          }
-
-          __gwt_metaProps[name] = value;
-
-        }
-
-      } else if (name == "gwt:onPropertyErrorFn") {
-
-        var content = meta.getAttribute("content");
-
-        if (content) {
-
-          try {
-
-            __gwt_onPropertyError = eval(content);
-
-          } catch (e) {
-
-            window.alert("Bad handler \"" + content + 
-
-              "\" for \"gwt:onPropertyErrorFn\"");
-
-          }
-
-        }
-
-      } else if (name == "gwt:onLoadErrorFn") {
-
-        var content = meta.getAttribute("content");
-
-        if (content) {
-
-          try {
-
-            __gwt_onLoadError = eval(content);
-
-          } catch (e) {
-
-            window.alert("Bad handler \"" + content + 
-
-              "\" for \"gwt:onLoadErrorFn\"");
-
-          }
-
-        }
-
-      }
-
-    }
-
-  }
-
-}
-
-
-
-/**
-
- * Determines the value of a deferred binding client property specified 
-
- * statically in host html.
-
- */
-
-function __gwt_getMetaProperty(name) {
-
-  var value = __gwt_metaProps[name];
-
-  if (value) {
-
-    return value;
-
-  } else {
-
-    return null;
-
-  }
-
-}
-
-
-
-/**
-
- * Determines whether or not a particular property value is allowed.
-
- * @param wnd the caller's window object (not $wnd!)
-
- * @param propName the name of the property being checked
-
- * @param propValue the property value being tested
-
- */
-
-function __gwt_isKnownPropertyValue(wnd, propName, propValue) {
-
-  return propValue in wnd["values$" + propName];
-
-}
-
-
-
-/**
-
- * Called by the selection script when a property has a bad value or is missing.
-
- * 'allowedValues' is an array of strings. Can be hooked in the host page using 
-
- * gwt:onPropertyErrorFn.
-
- */
-
-function __gwt_onBadProperty(moduleName, propName, allowedValues, badValue) {
-
-  if (__gwt_onPropertyError) {
-
-    __gwt_onPropertyError(moduleName, propName, allowedValues, badValue);
-
-    return;
-
-  } else {
-
-    var msg = "While attempting to load module \"" + moduleName + "\", ";
-
-    if (badValue != null) {
-
-       msg += "property \"" + propName + "\" was set to the unexpected value \"" 
-
-        + badValue + "\"";
-
-    } else {
-
-       msg += "property \"" + propName + "\" was not specified";
-
-    }
-
-    
-
-    msg += "\n\nAllowed values: " + allowedValues;
-
-   
-
-    window.alert(msg);
-
-  }
-
-}
-
-
-
-/**
-
- * Called directly from compiled code.
-
- */
-
-function __gwt_initHandlers(resize, beforeunload, unload) {
-
-   var oldOnResize = window.onresize;
-
-   window.onresize = function() {
-
-      resize();
-
-      if (oldOnResize)
-
-         oldOnResize();
-
-   };
-
-
-
-   var oldOnBeforeUnload = window.onbeforeunload;
-
-   window.onbeforeunload = function() {
-
-      var ret = beforeunload();
-
-
-
-      var oldRet;
-
-      if (oldOnBeforeUnload)
-
-        oldRet = oldOnBeforeUnload();
-
-
-
-      if (ret !== null)
-
-        return ret;
-
-      return oldRet;
-
-   };
-
-
-
-   var oldOnUnload = window.onunload;
-
-   window.onunload = function() {
-
-      unload();
-
-      if (oldOnUnload)
-
-         oldOnUnload();
-
-   };
-
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-
-// Hosted Mode
-
-//
-
-function __gwt_onUnloadHostedMode() {
-
-    window.external.gwtOnLoad(null, null);
-
-    if (__gwt_onUnloadHostedMode.oldUnloadHandler) {
-
-        __gwt_onUnloadHostedMode.oldUnloadHandler();
-
-    }
-
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-
-// Bootstrap
-
-//
-
-
-
-/**
-
- * Waits until all startup preconditions are satisfied, then launches the 
-
- * user-defined startup code for each module.
-
- */
-
-function __gwt_latchAndLaunch() {
-
-  var ready = true;
-
-  
-
-  // Are there any compilations still pending?
-
-  if (ready && !__gwt_moduleControlBlocks.isReady()) {
-
-    // Yes, we're still waiting on one or more compilations.
-
-    ready = false;
-
-  }
-
-
-
-  // Has the host html onload event fired?
-
-  if (ready && !__gwt_isHostPageLoaded) {
-
-    // No, the host html page hasn't fully loaded.
-
-    ready = false;
-
-  }
-
-  
-
-  // Are we ready to run user code?
-
-  if (ready) {
-
-    // Yes: run entry points.
-
-    __gwt_moduleControlBlocks.run();
-
-  } else {
-
-    // No: try again soon.
-
-    window.setTimeout(__gwt_latchAndLaunch, __gwt_retryWaitMillis);
-
-  }
-
-}
-
-
-
-/**
-
- * Starts the module-loading sequence after meta tags have been processed and
-
- * the body element exists.
-
- */
-
-function __gwt_loadModules() {
-
-  // Make sure the body element exists before starting.
-
-  if (!document.body) {
-
-    // Try again soon.
-
-    window.setTimeout(__gwt_loadModules, __gwt_retryWaitMillis);
-
-    return;
-
-  }
-
-
-
-  // Inject a frame for each module.
-
-  __gwt_moduleControlBlocks.injectFrames();
-
-
-
-  // Try to launch module entry points once everything is ready.
-
-  __gwt_latchAndLaunch();
-
-}
-
-
-
-/**
-
- * The very first thing to run, and it runs exactly once unconditionally.
-
- */
-
-function __gwt_bootstrap() {
-
-  // Hook onunload for hosted mode.
-
-  if (__gwt_isHosted()) {
-
-    __gwt_onUnloadHostedMode.oldUnloadHandler = window.onunload;
-
-    window.onunload = __gwt_onUnloadHostedMode;
-
-  }
-
-
-
-  // Hook the current window onload handler.
-
-  var oldHandler = window.onload;
-
-  window.onload = function() {
-
-    __gwt_isHostPageLoaded = true;
-
-    if (oldHandler) {
-
-      oldHandler();
-
-    }
-
-  };
-
-
-
-  // Parse meta tags from host html.
-
-  __gwt_processMetas();
-
-
-
-  // Load any modules.
-
-  __gwt_loadModules();
-
-}
-
-
-
-// Go.
-
-__gwt_bootstrap();
-

Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml	2007-06-21 00:14:58 UTC (rev 273)
+++ trunk/pom.xml	2007-06-22 07:53:56 UTC (rev 274)
@@ -98,6 +98,17 @@
 			</roles>
 			<timezone>+8</timezone>
 		</developer>
+		<developer>
+			<id>RobJellinghaus</id>
+			<name>Rob Jellinghaus</name>
+			<email>rjellinghaus at gmail.com</email>
+			<organization>RobJSoftware.org</organization>
+			<organizationUrl>http://robjsoftware.org</organizationUrl>
+			<roles>
+				<role>developer</role>
+			</roles>
+			<timezone>+8</timezone>
+		</developer>		
 	</developers>
 	<distributionManagement>
 		<downloadUrl>
@@ -211,10 +222,11 @@
 		<module>test</module>
 		<module>cdk</module>
 		<module>a4j-portlet</module>
+		<module>gwtjsf</module>
 	</modules>
 	<profiles>
 		<profile>
-			<id>gwt</id>
+			<id>gwtjsf</id>
 			<modules>
 				<module>gwtjsf</module>
 			</modules>




More information about the ajax4jsf-svn-commits mailing list