dev@jsftemplating.java.net

diffs for removing LayoutViewRoot & removing dynafaces hard dependency

From: Ken Paulsen <Ken.Paulsen_at_Sun.COM>
Date: Fri, 01 Feb 2008 17:14:26 -0800

Here are the diffs for the change to remove the LayoutViewRoot and to
remove the dynfaces dependency that JSFT currently has. The code
changes are done, but I have not finished cleaning up the javadoc (which
I'm doing now). Please review these changes and get back to me w/ any
questions / concerns.

I have tested this w/ dynafaces present, and w/o dynafaces present.
Both work fine. Only remaining regression is that the "decode" event
now no longer works for "pages." However, I think we can live w/o this
feature... if not, let me know and I'll find a way to make it work again.

Ken


? diff
? layout/ViewRootUtil.java
Index: component/factory/ComponentFactoryBase.java
===================================================================
RCS file: /cvs/jsftemplating/src/java/com/sun/jsftemplating/component/factory/ComponentFactoryBase.java,v
retrieving revision 1.23
diff -u -r1.23 ComponentFactoryBase.java
--- component/factory/ComponentFactoryBase.java 16 Aug 2007 23:21:38 -0000 1.23
+++ component/factory/ComponentFactoryBase.java 2 Feb 2008 01:10:15 -0000
@@ -32,7 +32,6 @@
 import javax.el.ValueExpression;
 import javax.faces.component.ActionSource;
 import javax.faces.component.UIComponent;
-import javax.faces.component.UIViewRoot;
 import javax.faces.context.FacesContext;
 
 import com.sun.jsftemplating.component.ComponentUtil;
Index: handlers/ComponentHandlers.java
===================================================================
RCS file: /cvs/jsftemplating/src/java/com/sun/jsftemplating/handlers/ComponentHandlers.java,v
retrieving revision 1.13
diff -u -r1.13 ComponentHandlers.java
--- handlers/ComponentHandlers.java 20 Nov 2007 19:15:34 -0000 1.13
+++ handlers/ComponentHandlers.java 2 Feb 2008 01:10:15 -0000
@@ -33,6 +33,7 @@
 import java.util.Map;
 
 import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
 import javax.faces.context.FacesContext;
 
 import com.sun.jsftemplating.annotation.Handler;
@@ -41,7 +42,6 @@
 import com.sun.jsftemplating.component.ComponentUtil;
 import com.sun.jsftemplating.layout.LayoutDefinitionManager;
 import com.sun.jsftemplating.layout.LayoutViewHandler;
-import com.sun.jsftemplating.layout.LayoutViewRoot;
 import com.sun.jsftemplating.layout.descriptors.LayoutComponent;
 import com.sun.jsftemplating.layout.descriptors.LayoutElement;
 import com.sun.jsftemplating.layout.descriptors.LayoutElementBase;
@@ -178,8 +178,8 @@
 
         // If they didn't give us a parent, make one one up...
         if (parent == null) {
- parent = new LayoutViewRoot();
- ((LayoutViewRoot) parent).setViewId("fake");
+ parent = new UIViewRoot();
+ ((UIViewRoot) parent).setViewId("fake");
         }
 
         // Build it...
Index: handlers/MetaDataHandlers.java
===================================================================
RCS file: /cvs/jsftemplating/src/java/com/sun/jsftemplating/handlers/MetaDataHandlers.java,v
retrieving revision 1.10
diff -u -r1.10 MetaDataHandlers.java
--- handlers/MetaDataHandlers.java 19 Apr 2007 01:19:25 -0000 1.10
+++ handlers/MetaDataHandlers.java 2 Feb 2008 01:10:15 -0000
@@ -36,7 +36,7 @@
 import com.sun.jsftemplating.annotation.HandlerInput;
 import com.sun.jsftemplating.annotation.HandlerOutput;
 import com.sun.jsftemplating.layout.LayoutDefinitionManager;
-import com.sun.jsftemplating.layout.LayoutViewRoot;
+import com.sun.jsftemplating.layout.ViewRootUtil;
 import com.sun.jsftemplating.layout.descriptors.ComponentType;
 import com.sun.jsftemplating.layout.descriptors.LayoutComponent;
 import com.sun.jsftemplating.layout.descriptors.LayoutDefinition;
@@ -157,15 +157,14 @@
 
     /**
      * <p> This handler finds the (closest) requested
- * <code>LayoutComponent</code> for the given <code>viewId</code> /
+ * {_at_link LayoutComponent} for the given <code>viewId</code> /
      * <code>clientId</code>. If the <code>viewId</code> is not supplied,
- * the current <code>UIViewRoot</code> will be used (NOTE: it must be
- * a {_at_link LayoutViewRoot}). The {_at_link LayoutComponent} is returned
- * via the <code>component</code> output parameter. If an exact match
- * is not found, it will return the last {_at_link LayoutComponent} found
- * while searching the tree -- this should be the last
- * {_at_link LayoutComponent} in the hierarchy of the specified
- * component.</p>
+ * the current <code>UIViewRoot</code> will be used. The
+ * {_at_link LayoutComponent} is returned via the <code>component</code>
+ * output parameter. If an exact match is not found, it will return
+ * the last {_at_link LayoutComponent} found while searching the tree --
+ * this should be the last {_at_link LayoutComponent} in the hierarchy
+ * of the specified component.</p>
      *
      * <p> This is not an easy process since JSF components may not all be
      * <code>NamingContainer</code>s, so the clientId is not sufficient to
@@ -203,19 +202,7 @@
         String viewId = (String) ctx.getInputValue("viewId");
 
         // Find the LayoutDefinition
- LayoutDefinition def = null;
- if (viewId == null) {
- // Determine from the current LayoutViewRoot (if possible)
- Object viewRoot = ctx.getFacesContext().getViewRoot();
- if (viewRoot instanceof LayoutViewRoot) {
- def = ((LayoutViewRoot) viewRoot).
- getLayoutDefinition(ctx.getFacesContext());
- }
- } else {
- // viewId specified, use that...
- def = LayoutDefinitionManager.getLayoutDefinition(
- ctx.getFacesContext(), viewId);
- }
+ LayoutDefinition def = ViewRootUtil.getLayoutDefinition(viewId);
 
         // Set the result
         ctx.setOutputValue("layoutDefinition", def);
Index: layout/LayoutDefinitionManager.java
===================================================================
RCS file: /cvs/jsftemplating/src/java/com/sun/jsftemplating/layout/LayoutDefinitionManager.java,v
retrieving revision 1.39
diff -u -r1.39 LayoutDefinitionManager.java
--- layout/LayoutDefinitionManager.java 20 Nov 2007 22:06:19 -0000 1.39
+++ layout/LayoutDefinitionManager.java 2 Feb 2008 01:10:16 -0000
@@ -160,6 +160,7 @@
     }
 
     /**
+// FIXME: Javadoc
      * <p> This method finds the (closest) requested
      * <code>LayoutComponent</code> for the given <code>clientId</code>.
      * If the <code>viewId</code> is not supplied, the current
@@ -191,7 +192,8 @@
                         "Unable to find LayoutDefinition ('" + ldKey + "')");
             }
         } else {
- layElt = ((LayoutViewRoot) ctx.getViewRoot()).getLayoutDefinition(ctx);
+ layElt = ViewRootUtil.getLayoutDefinition(
+ FacesContext.getCurrentInstance().getViewRoot());
         }
 
         // Save the current LayoutComposition Stack
Index: layout/LayoutViewHandler.java
===================================================================
RCS file: /cvs/jsftemplating/src/java/com/sun/jsftemplating/layout/LayoutViewHandler.java,v
retrieving revision 1.34
diff -u -r1.34 LayoutViewHandler.java
--- layout/LayoutViewHandler.java 18 Oct 2007 06:21:24 -0000 1.34
+++ layout/LayoutViewHandler.java 2 Feb 2008 01:10:16 -0000
@@ -78,13 +78,13 @@
  * <code>layout.dtd</code>.</p>
  *
  * <p> Besides the default <code>ViewHandler</code> behavior, this class is
- * responsible for instantiating a {_at_link LayoutViewRoot} and using the
- * given <code>viewId</code> as the {_at_link LayoutDefinition} key. It
- * will obtain the {_at_link LayoutDefinition}, initialize the declared
- * {_at_link Resource}s, and instantiate <code>UIComponent</code> tree using
- * the {_at_link LayoutDefinition}'s declared {_at_link LayoutComponent}
- * structure. During rendering, it delegates to the
- * {_at_link LayoutDefinition}.</p>
+ * responsible for using the given <code>viewId</code> as the
+ * {_at_link LayoutDefinition} key and setting it on the UIViewRoot that is
+ * created. It will obtain the {_at_link LayoutDefinition}, initialize the
+ * declared {_at_link Resource}s, and instantiate <code>UIComponent</code>
+ * tree using the {_at_link LayoutDefinition}'s declared
+ * {_at_link LayoutComponent} structure. During rendering, it delegates to
+ * the {_at_link LayoutDefinition}.</p>
  *
  * @author Ken Paulsen (ken.paulsen_at_sun.com)
  */
@@ -128,7 +128,7 @@
 
         // Check to see if jsftemplating should create the view
         if(!this.isMappedView(viewId)) {
- UIViewRoot viewRoot = this._oldViewHandler.createView(context, viewId);
+ UIViewRoot viewRoot = _oldViewHandler.createView(context, viewId);
             return viewRoot;
         }
 
@@ -140,22 +140,21 @@
         // one for the initial case.
         if (context.getViewRoot() != null) {
             UIViewRoot oldViewRoot = context.getViewRoot();
- if ((oldViewRoot instanceof LayoutViewRoot)
- && oldViewRoot.getViewId().equals(viewId)) {
+ LayoutDefinition oldLD = ViewRootUtil.getLayoutDefinition(oldViewRoot);
+ if ((oldLD != null) && oldViewRoot.getViewId().equals(viewId)) {
                 // If you navigate to the page you are already on, JSF will
                 // re-create the UIViewRoot of the current page. The initPage
                 // event needs to be reset so that it will re-execute itself.
- ((LayoutViewRoot) oldViewRoot).getLayoutDefinition(context).
- setInitPageExecuted(context, Boolean.FALSE);
+ oldLD.setInitPageExecuted(context, Boolean.FALSE);
             }
             locale = context.getViewRoot().getLocale();
             renderKitId = context.getViewRoot().getRenderKitId();
         }
 
- // Create the LayoutViewRoot
- LayoutViewRoot viewRoot = new LayoutViewRoot();
+ // Create the ViewRoot
+ UIViewRoot viewRoot = _oldViewHandler.createView(context, viewId);
         viewRoot.setViewId(viewId);
- viewRoot.setLayoutDefinitionKey(viewId);
+ ViewRootUtil.setLayoutDefinitionKey(viewRoot, viewId);
 
         // if there was no locale from the previous view, calculate the locale
         // for this view.
@@ -185,7 +184,7 @@
         // Initialize Resources / Create Tree
         LayoutDefinition def = null;
         try {
- def = viewRoot.getLayoutDefinition(context);
+ def = ViewRootUtil.getLayoutDefinition(viewRoot);
         } catch (LayoutDefinitionException ex) {
             if (LogUtil.configEnabled()) {
                 LogUtil.config("JSFT0005", (Object) viewId);
@@ -278,7 +277,7 @@
         context.responseComplete();
 
         // Create dummy UIViewRoot
- UIViewRoot root = new LayoutViewRoot();
+ UIViewRoot root = new UIViewRoot();
         root.setRenderKitId("dummy");
 
         // Setup the FacesStreamerContext
@@ -566,7 +565,7 @@
         // Perform default behavior...
         UIViewRoot root = _oldViewHandler.restoreView(context, viewId);
 
- // Return the UIViewRoot (LayoutViewRoot most likely)
+ // Return the UIViewRoot
         return root;
     }
 
@@ -575,11 +574,7 @@
      */
     public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException {
         // Make sure we have a def
- LayoutDefinition def = null;
- if (viewToRender instanceof LayoutViewRoot) {
- def = ((LayoutViewRoot) viewToRender).getLayoutDefinition(context);
- }
-
+ LayoutDefinition def = ViewRootUtil.getLayoutDefinition(viewToRender);
         if (def == null) {
             // No def, fall back to default behavior
             _oldViewHandler.renderView(context, viewToRender);
@@ -588,16 +583,8 @@
             ResponseWriter writer = setupResponseWriter(context);
             writer.startDocument();
 
-// BEGIN EXPERIMENTAL CODE...
- UIComponent target = (UIComponent) context.getExternalContext().
- getRequestMap().get(AJAX_REQ_TARGET_KEY);
- if (target != null) {
- renderComponent(context, target);
- } else {
-// END EXPERIMENTAL CODE...
- // Render content
- def.encode(context, viewToRender);
- }
+ // Render content
+ def.encode(context, viewToRender);
 
             // End document
             writer.endDocument();
@@ -700,9 +687,8 @@
     public void writeState(FacesContext context) throws IOException {
         // Check to see if we should delegate back to the legacy ViewHandler
         UIViewRoot root = context.getViewRoot();
- if ((root == null) || !(root instanceof LayoutViewRoot)
- || (((LayoutViewRoot) root).
- getLayoutDefinition(context) == null)) {
+ if ((root == null)
+ || (ViewRootUtil.getLayoutDefinition(root) == null)) {
             // Use old behavior...
             _oldViewHandler.writeState(context);
         } else {
Index: layout/descriptors/LayoutComponent.java
===================================================================
RCS file: /cvs/jsftemplating/src/java/com/sun/jsftemplating/layout/descriptors/LayoutComponent.java,v
retrieving revision 1.11
diff -u -r1.11 LayoutComponent.java
--- layout/descriptors/LayoutComponent.java 7 Aug 2007 22:45:08 -0000 1.11
+++ layout/descriptors/LayoutComponent.java 2 Feb 2008 01:10:16 -0000
@@ -29,13 +29,14 @@
 import java.util.Map;
 
 import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
 import javax.faces.context.FacesContext;
 
 import com.sun.jsftemplating.component.ChildManager;
 import com.sun.jsftemplating.component.ComponentUtil;
 import com.sun.jsftemplating.component.TemplateComponent;
 import com.sun.jsftemplating.el.VariableResolver;
-import com.sun.jsftemplating.layout.LayoutViewRoot;
+import com.sun.jsftemplating.layout.ViewRootUtil;
 import com.sun.jsftemplating.layout.descriptors.handler.Handler;
 import com.sun.jsftemplating.layout.event.AfterCreateEvent;
 import com.sun.jsftemplating.layout.event.AfterEncodeEvent;
@@ -423,9 +424,10 @@
                         == getLayoutDefinition()) {
                     name = getUnevaluatedId();
                 }
- } else if (parent instanceof LayoutViewRoot) {
- // NOTE: I am not checking for UIViewRoot b/c I don't want to
- // use a facet unless we're using JSFT's LayoutViewRoot
+ } else if ((parent instanceof UIViewRoot) && (ViewRootUtil.
+ getLayoutDefinition((UIViewRoot) parent) != null)) {
+
+ // NOTE: Only set the name if its a JSFT ViewRoot
                 name = getUnevaluatedId();
             }
         }
Index: layout/descriptors/LayoutDefinition.java
===================================================================
RCS file: /cvs/jsftemplating/src/java/com/sun/jsftemplating/layout/descriptors/LayoutDefinition.java,v
retrieving revision 1.13
diff -u -r1.13 LayoutDefinition.java
--- layout/descriptors/LayoutDefinition.java 16 Aug 2007 23:04:21 -0000 1.13
+++ layout/descriptors/LayoutDefinition.java 2 Feb 2008 01:10:16 -0000
@@ -28,16 +28,17 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.lang.reflect.Method;
 
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIViewRoot;
 import javax.faces.context.FacesContext;
 
-import com.sun.faces.extensions.avatar.lifecycle.AsyncResponse;
 import com.sun.jsftemplating.component.TemplateComponent;
 import com.sun.jsftemplating.layout.descriptors.handler.Handler;
 import com.sun.jsftemplating.layout.event.DecodeEvent;
 import com.sun.jsftemplating.layout.event.InitPageEvent;
+import com.sun.jsftemplating.util.Util;
 
 /**
  * <p> This represents the top-level {_at_link LayoutElement}, it is the
@@ -219,13 +220,12 @@
     public void encode(FacesContext context, UIComponent component) throws IOException {
         if (component instanceof UIViewRoot) {
             component.encodeBegin(context);
- AsyncResponse async = AsyncResponse.getInstance(false);
- if ((async == null) || !AsyncResponse.isAjaxRequest() || async.isRenderAll()) {
- // This is not an ajax request... behave normal
- super.encode(context, component);
- } else {
+ if (isDynaFacesRequest()) {
                 // Dynamic Faces is now overriding this, so this is required...
                 component.encodeChildren(context);
+ } else {
+ // This is not an ajax request... behave normal
+ super.encode(context, component);
             }
             component.encodeEnd(context);
         } else {
@@ -234,6 +234,41 @@
     }
 
     /**
+ * <p> This method reflectively calls dyna-faces to determine if this
+ * request will be handled by dynafaces.</p>
+ */
+ private boolean isDynaFacesRequest() {
+ if (_asyncResponseClass == null) {
+ // DynamicFaces not installed, abort
+ return false;
+ }
+
+ // Check the request...
+ boolean result = false;
+ try {
+ // See if this is an DynaFaces Ajax request
+ result = ((Boolean) _asyncResponseIsAjaxRequest.invoke(null)).
+ booleanValue();
+ if (result) {
+ // See if this is a "render all" ajax request, in which case
+ // we'll consider it NOT to be an Ajax request.
+ Object async = _asyncResponseGetInstance.invoke(null,
+ Boolean.FALSE);
+ result = !((Boolean) _asyncResponseIsRenderAll.invoke(async)).
+ booleanValue();
+ }
+ } catch (Exception ex) {
+// FIXME: Log
+System.out.println("Incorrect Dynafaces Version?");
+ex.printStackTrace();
+ return false;
+ }
+
+ // Return the answer
+ return result;
+ }
+
+ /**
      * <p> The <code>LayoutDefinition</code> does not encode anything for
      * itself, this method simply returns true.</p>
      *
@@ -349,6 +384,20 @@
         ctx.getExternalContext().getRequestMap().put(key, value);
     }
 
+ /**
+ * <p> This method eats the exception that might be thrown when locating
+ * a class.</p>
+ */
+ private static Class loadClass(String className, Object obj) {
+ Class result = null;
+ try {
+ result = Util.loadClass(className, obj);
+ } catch (ClassNotFoundException ex) {
+ // Eat it.
+ }
+ return result;
+ }
+
 
     /**
      *
@@ -399,4 +448,30 @@
      * information about the <code>LayoutDefinition</code>.</p>
      */
     private Map<String, Object> _attributes = new HashMap<String, Object>();
+
+ /**
+ * <p> The DynamicFaces AsyncResponse Class.</p>
+ */
+ private static final Class _asyncResponseClass;
+ private static final Method _asyncResponseGetInstance;
+ private static final Method _asyncResponseIsAjaxRequest;
+ private static final Method _asyncResponseIsRenderAll;
+
+ static {
+ // Initialize the DynamicFaces variables
+ _asyncResponseClass = loadClass(
+ "com.sun.faces.extensions.avatar.lifecycle.AsyncResponse", null);
+ if (_asyncResponseClass != null) {
+ _asyncResponseGetInstance =
+ Util.getMethod(_asyncResponseClass, "getInstance", Boolean.TYPE);
+ _asyncResponseIsAjaxRequest =
+ Util.getMethod(_asyncResponseClass, "isAjaxRequest");
+ _asyncResponseIsRenderAll =
+ Util.getMethod(_asyncResponseClass, "isRenderAll");
+ } else {
+ _asyncResponseGetInstance = null;
+ _asyncResponseIsAjaxRequest = null;
+ _asyncResponseIsRenderAll = null;
+ }
+ }
 }
Index: util/Util.java
===================================================================
RCS file: /cvs/jsftemplating/src/java/com/sun/jsftemplating/util/Util.java,v
retrieving revision 1.12
diff -u -r1.12 Util.java
--- util/Util.java 25 Apr 2007 20:58:14 -0000 1.12
+++ util/Util.java 2 Feb 2008 01:10:17 -0000
@@ -23,6 +23,7 @@
 package com.sun.jsftemplating.util;
 
 import java.io.InputStream;
+import java.lang.reflect.Method;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
@@ -140,6 +141,24 @@
     }
 
     /**
+ * <p> This method locates the requested <code>Method</code> on the
+ * given <code>Class</code>, with the given <code>params</code>. This
+ * method does not throw any exceptions. Instead it will return
+ * <code>null</code> if unable to locate the method.</p>
+ */
+ public static Method getMethod(Class cls, String name, Class ... prms) {
+ Method method = null;
+ try {
+ method = cls.getMethod(name, prms);
+ } catch (NoSuchMethodException ex) {
+ // Do nothing, we're eating the exception
+ } catch (SecurityException ex) {
+ // Do nothing, we're eating the exception
+ }
+ return method;
+ }
+
+ /**
      * <p> This method converts the given Map into a Properties Map (if it is
      * already one, then it simply returns the given Map).</p>
      */