dev@javaserverfaces.java.net

Checking in Andy's 180-TreeVisitor API

From: Ed Burns <Ed.Burns_at_Sun.COM>
Date: Tue, 09 Dec 2008 18:52:28 -0800

I am very impressed with the completeness of Andy's work on this. The
effort required to integrate it is the easiest of any contributed by the
EG on JSR-314-EG.

All the automated tests continue to run to completion without failure.

Andy and the EG are still tweaking this but it's solid enough to put in
right now.

Issue: 180 TreeVisitor

author: Andy Schwartz

r=edburns


SECTION: Modified Files
----------------------------
M jsf-api/doc/web-facesconfig_2_0.xsd

- add visit-context-factory element inside of factoryType

M jsf-api/src/javax/faces/FactoryFinder.java
M jsf-ri/src/com/sun/faces/jsf-ri-config.xml
M jsf-ri/src/com/sun/faces/config/processor/FactoryConfigProcessor.java

- add VisitContextFactory

M jsf-api/src/javax/faces/component/UIComponent.java
M jsf-api/src/javax/faces/component/UIData.java
M jsf-api/src/javax/faces/component/UIViewRoot.java
M jsf-ri/src/com/sun/faces/lifecycle/RestoreViewPhase.java

- Change doTreeTraversal to visitTree().

A jsf-api/src/javax/faces/component/visit/VisitHint.java
A jsf-api/src/javax/faces/component/visit/VisitContext.java
A jsf-api/src/javax/faces/component/visit/VisitContextWrapper.java
A jsf-api/src/javax/faces/component/visit/VisitCallback.java
A jsf-api/src/javax/faces/component/visit/VisitContextFactory.java
A jsf-api/src/javax/faces/component/visit/VisitResult.java

- New package from Andy. See http://archives.java.sun.com/cgi-bin/wa?A2=ind0812&L=JSR-314-EG&T=0&F=&S=&X=44CF4B0105AF6A4C0E&Y=ed.burns%40sun.com&P=4826

A jsf-ri/src/com/sun/faces/component/visit/PartialVisitContext.java
A jsf-ri/src/com/sun/faces/component/visit/FullVisitContext.java
A jsf-ri/src/com/sun/faces/component/visit/VisitContextFactoryImpl.java

- Concrete implementations of VisitContext.

A jsf-demo/tree-visit/src/main/java/treevisit/Bean.java
A jsf-demo/tree-visit/src/main/webapp/home.xhtml
A jsf-demo/tree-visit/src/main/webapp/WEB-INF
A jsf-demo/tree-visit/src/main/webapp/WEB-INF/faces-config.xml
A jsf-demo/tree-visit/src/main/webapp/WEB-INF/web.xml
A jsf-demo/tree-visit/src/main/webapp/index.html
A jsf-demo/tree-visit/src/main/webapp/resources/stylesheet.css
A jsf-demo/tree-visit/src/main/webapp/resources/redwaveani.gif
A jsf-demo/tree-visit/pom.xml
A jsf-demo/tree-visit/build.xml

- Excellent demo app from Andy.

SECTION: Diffs
----------------------------
Index: jsf-api/doc/web-facesconfig_2_0.xsd
===================================================================
--- jsf-api/doc/web-facesconfig_2_0.xsd (revision 6051)
+++ jsf-api/doc/web-facesconfig_2_0.xsd (working copy)
 -712,6 +712,20 @@
                     </xsd:documentation>
                 </xsd:annotation>
             </xsd:element>
+ <xsd:element name="visit-context-factory"
+ type="javaee:fully-qualified-classType">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ The "visit-context-factory" element contains the fully
+ qualified class name of the concrete VisitContextFactory
+ implementation class that will be called when
+ FactoryFinder.getFactory(VISIT_CONTEXT_FACTORY) is
+ called.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
             <xsd:element name="factory-extension"
                          type="javaee:faces-config-factory-extensionType"
                          minOccurs="0"
Index: jsf-api/src/javax/faces/FactoryFinder.java
===================================================================
--- jsf-api/src/javax/faces/FactoryFinder.java (revision 6051)
+++ jsf-api/src/javax/faces/FactoryFinder.java (working copy)
 -173,6 +173,13 @@
 
     /**
      * <p>The property name for the
+ * {_at_link javax.faces.component.visit.VisitContextFactory} class name.</p>
+ */
+ public final static String VISIT_CONTEXT_FACTORY =
+ "javax.faces.component.visit.VisitContextFactory";
+
+ /**
+ * <p>The property name for the
      * {_at_link javax.faces.lifecycle.LifecycleFactory} class name.</p>
      */
     public final static String LIFECYCLE_FACTORY =
 -206,6 +213,7 @@
      */
     private static final String[] FACTORY_NAMES = {
          APPLICATION_FACTORY,
+ VISIT_CONTEXT_FACTORY,
          EXCEPTION_HANDLER_FACTORY,
          FACES_CONTEXT_FACTORY,
          LIFECYCLE_FACTORY,
 -581,8 +589,12 @@
             factoryClasses = new HashMap<String, Class>(FACTORY_NAMES.length);
             factoryClasses.put(APPLICATION_FACTORY,
                  javax.faces.application.ApplicationFactory.class);
+ factoryClasses.put(EXCEPTION_HANDLER_FACTORY,
+ javax.faces.context.ExceptionHandlerFactory.class);
             factoryClasses.put(FACES_CONTEXT_FACTORY,
                  javax.faces.context.FacesContextFactory.class);
+ factoryClasses.put(VISIT_CONTEXT_FACTORY,
+ javax.faces.component.visit.VisitContextFactory.class);
             factoryClasses.put(LIFECYCLE_FACTORY,
                  javax.faces.lifecycle.LifecycleFactory.class);
             factoryClasses.put(RENDER_KIT_FACTORY,
Index: jsf-api/src/javax/faces/component/UIComponent.java
===================================================================
--- jsf-api/src/javax/faces/component/UIComponent.java (revision 6051)
+++ jsf-api/src/javax/faces/component/UIComponent.java (working copy)
 -65,6 +65,8 @@
 import javax.faces.FacesException;
 import javax.faces.FacesWrapper;
 import javax.faces.application.Resource;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
 import javax.faces.context.FacesContext;
 import javax.faces.el.ValueBinding;
 import javax.faces.event.AbortProcessingException;
 -1301,18 +1303,23 @@
      * for each node encountered.
      * @since 2.0
      */
- public void doTreeTraversal(FacesContext context,
- ContextCallback nodeCallback) {
- nodeCallback.invokeContextCallback(context, this);
+ public void visitTree(VisitContext context,
+ VisitCallback nodeCallback) {
+ if (this.isVisitable(context)) {
+ context.invokeVisitCallback(this, nodeCallback);
+ }
 
         Iterator<UIComponent> it = this.getFacetsAndChildren();
         
         while(it.hasNext()) {
- it.next().doTreeTraversal(context, nodeCallback);
+ it.next().visitTree(context, nodeCallback);
         }
-
     }
     
+ public boolean isVisitable(VisitContext context) {
+ return true;
+ }
+
 
 
     /**
Index: jsf-api/src/javax/faces/component/UIData.java
===================================================================
--- jsf-api/src/javax/faces/component/UIData.java (revision 6051)
+++ jsf-api/src/javax/faces/component/UIData.java (working copy)
 -66,9 +66,11 @@
 
 
 // ------------------------------------------------------------- Private Classes
+import javax.faces.component.visit.VisitCallback;
 
 
 // Private class to represent saved state information
+import javax.faces.component.visit.VisitContext;
 /**
  * <p><strong>UIData</strong> is a {_at_link UIComponent} that supports data
  * binding to a collection of data objects represented by a {_at_link DataModel}
 -958,7 +960,7 @@
     }
 
     @Override
- public void doTreeTraversal(FacesContext context, ContextCallback contextCallback) {
+ public void visitTree(VisitContext context, VisitCallback contextCallback) {
         /******* PENDING(edburns) this is disabled until we fix UIData StateSaving
         processFacets(context, contextCallback);
         processColumnFacets(context, contextCallback);
 -966,16 +968,16 @@
         ***********/
     }
 
- private void processFacets(FacesContext context, ContextCallback contextCallback) {
+ private void processFacets(VisitContext context, VisitCallback contextCallback) {
         Iterator<UIComponent> it = getFacets().values().iterator();
 
         while (it.hasNext()) {
- it.next().doTreeTraversal(context, contextCallback);
+ it.next().visitTree(context, contextCallback);
         }
     }
 
- private void processColumnFacets(FacesContext context,
- ContextCallback contextCallback) {
+ private void processColumnFacets(VisitContext context,
+ VisitCallback contextCallback) {
         Iterator<UIComponent> childIter = getChildren().iterator();
 
         while (childIter.hasNext()) {
 -987,14 +989,14 @@
 
                 Iterator<UIComponent> facetsIter = child.getFacets().values().iterator();
                 while (facetsIter.hasNext()) {
- facetsIter.next().doTreeTraversal(context, contextCallback);
+ facetsIter.next().visitTree(context, contextCallback);
                 }
             }
         }
     }
 
- private void processColumnChildren(FacesContext context,
- ContextCallback contextCallback) {
+ private void processColumnChildren(VisitContext context,
+ VisitCallback contextCallback) {
         int first = getFirst();
         int rows = getRows();
         int last;
 -1020,7 +1022,7 @@
                     }
                     Iterator<UIComponent> columnChildIter = child.getChildren().iterator();
                     while ( columnChildIter.hasNext()) {
- columnChildIter.next().doTreeTraversal(context, contextCallback);
+ columnChildIter.next().visitTree(context, contextCallback);
                     }
                 }
             }
Index: jsf-api/src/javax/faces/component/UIViewRoot.java
===================================================================
--- jsf-api/src/javax/faces/component/UIViewRoot.java (revision 6051)
+++ jsf-api/src/javax/faces/component/UIViewRoot.java (working copy)
 -48,10 +48,9 @@
 import javax.faces.FactoryFinder;
 import javax.faces.application.PartialTraversal;
 import javax.faces.application.ProjectStage;
-import javax.faces.context.ExternalContext;
+import javax.faces.component.visit.VisitResult;
 import javax.faces.context.FacesContext;
 import javax.faces.context.PartialViewContext;
-import javax.faces.context.ResponseWriter;
 import javax.faces.event.AbortProcessingException;
 import javax.faces.event.FacesEvent;
 import javax.faces.event.PhaseEvent;
 -72,13 +71,14 @@
 import java.util.ListIterator;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
 import javax.faces.event.AfterRestoreStateEvent;
 import javax.faces.event.ViewMapCreatedEvent;
 import javax.faces.event.ViewMapDestroyedEvent;
 import javax.faces.event.ExceptionEvent;
 import javax.faces.event.ExceptionEventContext;
 
-import javax.servlet.http.HttpServletResponse;
 
 /**
  * <p><strong class="changed_modified_2_0">UIViewRoot</strong> is the
 -831,7 +831,7 @@
      * FacesEvent}s remain in the event queue, that any
      * <code>PhaseListener</code>s in {_at_link #getPhaseListeners} are
      * invoked as appropriate, and that the <code>this.{_at_link
- * UIComponent#doTreeTraversal} is called, passing a {_at_link
+ * UIComponent#visitTree} is called, passing a {_at_link
      * ContextCallback} that takes the following action: call the {_at_link
      * UIComponent#processEvent} method of the current component. The
      * argument <code>event</code> must be an instance of {_at_link
 -853,11 +853,13 @@
             notifyAfter(context, PhaseId.RESTORE_VIEW);
             final AfterRestoreStateEvent event = new AfterRestoreStateEvent(this);
             try {
- this.doTreeTraversal(context, new ContextCallback() {
+ this.visitTree(VisitContext.createVisitContext(context),
+ new VisitCallback() {
 
- public void invokeContextCallback(FacesContext context, UIComponent target) {
+ public VisitResult visit(VisitContext context, UIComponent target) {
                         event.setComponent(target);
                         target.processEvent(event);
+ return VisitResult.ACCEPT;
                     }
                 });
             } catch (AbortProcessingException e) {
Index: jsf-api/src/javax/faces/component/visit/VisitHint.java
===================================================================
--- jsf-api/src/javax/faces/component/visit/VisitHint.java (revision 0)
+++ jsf-api/src/javax/faces/component/visit/VisitHint.java (revision 0)
 -0,0 +1,67 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package javax.faces.component.visit;
+
+/**
+ * <p class="changed_added_2_0">An enum that specifies hints that impact
+ * the behavior of a component tree visit.</p>
+
+ * RELEASE_PENDING
+ *
+ * @see VisitContext#getHints VisitContext.getHints()
+ *
+ * @since 2.0
+ */
+public enum VisitHint {
+
+ /**
+ * Hint that indicates that only the rendered subtree should be visited.
+ */
+ VISIT_RENDERED,
+
+ /**
+ * Hint that indicates that components that iterate over their children
+ * (such as {_at_link javax.faces.component.UIData UIData} should perform
+ * their normal iteration during the tree visit.
+ */
+ VISIT_ITERATED,
+
+ /**
+ * Hint that indicates that transient components should be visited.
+ */
+ VISIT_TRANSIENT
+}
Index: jsf-api/src/javax/faces/component/visit/VisitContext.java
===================================================================
--- jsf-api/src/javax/faces/component/visit/VisitContext.java (revision 0)
+++ jsf-api/src/javax/faces/component/visit/VisitContext.java (revision 0)
 -0,0 +1,177 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package javax.faces.component.visit;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import javax.faces.FactoryFinder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ * <p class="changed_added_2_0">A context object that is used to hold
+ * state relating to a component tree visit.</p>
+ *
+ * RELEASE_PENDING
+ *
+ * <p>Component tree visits are initiated by calling
+ * {_at_link UIComponent#visitTree UIComponent.visitTree()},
+ * at which point both a {_at_link VisitContext} and a {_at_link VisitCallback}
+ * must be provided. <p>The {_at_link FullVisitContext} should be used when
+ * performing a visit over the entire component tree. The
+ * {_at_link PartialVisitContext} is used when visiting a subset of the
+ * component tree</p>
+ *
+ * @see UIComponent#visitTree UIComponent.visitTree()
+ * @see VisitCallback
+ * @see FullVisitContext
+ * @see PartialVisitContext
+ *
+ * @since 2.0
+ */
+abstract public class VisitContext {
+
+ // Design notes: The VisitContext contract could be defined
+ // as an interface. However, there is the potential that we
+ // may need to add new methods in the future, so leaving as
+ // an abstract class in order to have room to grow.
+ //
+ // Since we are an abstract class rather than an interface,
+ // we could provide implementations of of some of the simpler
+ // methods (eg. getFacesContext() and getHints()) to avoid
+ // duplicating this code in VisitContext implementations.
+ // However, doing so would mean that "wrapping" VisitContext
+ // implementations would be forced to pick up such implementations,
+ // so going with a pure contract (no implementation).
+
+ /**
+ * <p>This unmodifiable Collection is returned by
+ * VisitContext.getIdsToVisit() in cases where all ids
+ * should be visited.</p>
+ */
+ // Note: We cannot use Collections.emptyList() as that returns
+ // a shared instance - we want to unique instance to allow for
+ // identity tests.
+ static public final Collection<String> ALL_IDS =
+ Collections.unmodifiableCollection(new ArrayList<String>(0));
+
+ /**
+ * <p>Returns the FacesContext for the current request.</p>
+ */
+ abstract public FacesContext getFacesContext();
+
+ /**
+ * <p>
+ * Given a NamingContainer component, returns the client ids of
+ * any components underneath the NamingContainer that should be
+ * visited.
+ * </p>
+ * <p>
+ * This method is called by NamingContainer visitTree() implementations
+ * to determine whether the NamingContainer contains components to be
+ * visited. In the case where no such components exist, the
+ * NamingContainer can short-circuit the tree visit and avoid
+ * descending into child subtrees.
+ * </p>
+ * <p>
+ * In addition, iterating components such as UIData may be able to
+ * use the returned ids to determine which iterated states (ie. rows)
+ * need to be visited. This allows the visit traversal to be
+ * contstrained such only those rows that contain visit targets
+ * need to be traversed.
+ * </p>
+ * @param component a NamingContainer component
+ * @return an unmodifiable Collection containing the client ids of
+ * any components underneath the NamingContainer that are known to be
+ * targets of the tree visit. If no such components exist, returns
+ * an empty Collection. If all components underneath the
+ * NamingContainer should be visited, returns the
+ * {_at_code VisitContext.ALL_IDS} collection.
+ * @throws IllegalArgumentException if {_at_code component} is not
+ * an instance of NamingContainer
+ */
+ abstract public Collection<String> getIdsToVisit(UIComponent component);
+
+ /**
+ * <p>Called by {_at_link UIComponent#visitTree UIComponent.visitTree()}
+ * to visit a single component.</p>
+ *
+ * @param component the component to visit
+ * @param callback the VisitCallback to call
+ * @return a VisitResult value that indicates whether to continue
+ * visiting the component's subtree, skip visiting the component's
+ * subtree or abort the visit altogether.
+ */
+ abstract public VisitResult invokeVisitCallback(UIComponent component,
+ VisitCallback callback);
+
+ /**
+ * <p>Returns hints that influence the behavior of the tree visit.</p>
+ *
+ * <p>Interested parties, such as
+ * {_at_link UIComponent#visitTree UIComponent.visitTree()} implementations,
+ * may check to see whether a particular hint is present by calling
+ * {_at_code VisitContext.getHints().contains()}, passing in one of the
+ * hints defined by {_at_link VisitHint}.
+ *
+ * @return a non-empty, unmodifiable collection of VisitHints
+ */
+ abstract public Set<VisitHint> getHints();
+
+ public static VisitContext createVisitContext(FacesContext context,
+ Collection<String> ids, Set<VisitHint> hints) {
+ VisitContext result = null;
+ VisitContextFactory factory = (VisitContextFactory)
+ FactoryFinder.getFactory(FactoryFinder.VISIT_CONTEXT_FACTORY);
+ result = factory.getVisitContext(context, ids, hints);
+ return result;
+ }
+
+ public static VisitContext createVisitContext(FacesContext context) {
+ VisitContext result = null;
+
+ VisitContextFactory factory = (VisitContextFactory)
+ FactoryFinder.getFactory(FactoryFinder.VISIT_CONTEXT_FACTORY);
+ result = factory.getVisitContext(context, null, null);
+
+ return result;
+ }
+}
Index: jsf-api/src/javax/faces/component/visit/VisitContextWrapper.java
===================================================================
--- jsf-api/src/javax/faces/component/visit/VisitContextWrapper.java (revision 0)
+++ jsf-api/src/javax/faces/component/visit/VisitContextWrapper.java (revision 0)
 -0,0 +1,83 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package javax.faces.component.visit;
+
+import java.util.Collection;
+import java.util.Set;
+import javax.faces.FacesWrapper;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+/**
+ * <p>Provides a simple implementation of {_at_link ExceptionHandler} that can
+ * be subclassed by developers wishing to provide specialized behavior
+ * to an existing {_at_link ExceptionHandler} instance. The default
+ * implementation of all methods is to call through to the wrapped
+ * {_at_link ExceptionHandler} instance.</p>
+ *
+ * <p>Usage: extend this class and override {_at_link #getWrapped} to
+ * return the instance we are wrapping.</p>
+ *
+ * @since 2.0
+ */
+public abstract class VisitContextWrapper extends VisitContext implements FacesWrapper<VisitContext>{
+
+ @Override
+ public FacesContext getFacesContext() {
+ return getWrapped().getFacesContext();
+ }
+
+ @Override
+ public Set<VisitHint> getHints() {
+ return getWrapped().getHints();
+ }
+
+ @Override
+ public Collection<String> getIdsToVisit(UIComponent component) {
+ return getWrapped().getIdsToVisit(component);
+ }
+
+ @Override
+ public VisitResult invokeVisitCallback(UIComponent component, VisitCallback callback) {
+ return getWrapped().invokeVisitCallback(component, callback);
+ }
+
+ public abstract VisitContext getWrapped();
+
+
+
+}
Index: jsf-api/src/javax/faces/component/visit/VisitCallback.java
===================================================================
--- jsf-api/src/javax/faces/component/visit/VisitCallback.java (revision 0)
+++ jsf-api/src/javax/faces/component/visit/VisitCallback.java (revision 0)
 -0,0 +1,72 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package javax.faces.component.visit;
+
+import javax.faces.component.UIComponent;
+
+/**
+ *
+ * <p class="changed_added_2_0">A simple callback interface that enables
+ * taking action on a specific UIComponent (either facet or child) during
+ * a component tree visit.</p>
+ *
+ * RELEASE_PENDING
+ *
+ * @see UIComponent#visitTree UIComponent.visitTree()
+ *
+ * @since 2.0
+ */
+public interface VisitCallback {
+
+ /**
+ * <p>This method is called during component tree visits by
+ * {_at_link VisitContext#invokeVisitCallback VisitContext.invokeVisitCallback()}
+ * to visit the specified component. At the point in time when this
+ * method is called, the argument {_at_code target} is guaranteed
+ * to be in the proper state with respect to its ancestors in the
+ * View.</p>
+ *
+ * @param context the {_at_link VisitContext} for this tree visit.
+ *
+ * @param target the {_at_link UIComponent} to visit
+ *
+ * @return a {_at_link VisitResult} that indicates whether to continue
+ * visiting the component's subtree, skip visiting the component's
+ * subtree or end the visit.
+ */
+ public VisitResult visit(VisitContext context, UIComponent target);
+}
Index: jsf-api/src/javax/faces/component/visit/VisitContextFactory.java
===================================================================
--- jsf-api/src/javax/faces/component/visit/VisitContextFactory.java (revision 0)
+++ jsf-api/src/javax/faces/component/visit/VisitContextFactory.java (revision 0)
 -0,0 +1,64 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package javax.faces.component.visit;
+
+import java.util.Collection;
+import java.util.Set;
+import javax.faces.FacesWrapper;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ * @since 2.0
+ */
+public abstract class VisitContextFactory implements FacesWrapper<VisitContextFactory> {
+
+ /**
+ * <p class="changed_added_2_0">If this factory has been decorated, the
+ * implementation doing the decorating may override this method to provide
+ * access to the implementation being wrapped. A default implementation
+ * is provided that returns <code>null</code>.</p>
+ */
+ public VisitContextFactory getWrapped() {
+ return null;
+ }
+
+
+ public abstract VisitContext getVisitContext(FacesContext context,
+ Collection<String> ids, Set<VisitHint> hints);
+
+}
Index: jsf-api/src/javax/faces/component/visit/VisitResult.java
===================================================================
--- jsf-api/src/javax/faces/component/visit/VisitResult.java (revision 0)
+++ jsf-api/src/javax/faces/component/visit/VisitResult.java (revision 0)
 -0,0 +1,69 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package javax.faces.component.visit;
+
+/**
+ *
+ * <p class="changed_added_2_0">An enum that specifies the possible
+ * results of a call to {_at_link VisitCallback#visit VisitCallback.visit()}.
+ * </p>
+ *
+ * RELEASE_PENDING
+ *
+ * @see VisitCallback#visit VisitCallback.visit()
+ *
+ * @since 2.0
+ */
+public enum VisitResult {
+
+ /**
+ * This result indicates that the tree visit should descend into
+ * current component's subtree.
+ */
+ ACCEPT,
+
+ /**
+ * This result indicates that the tree visit should continue, but
+ * should skip the current component's subtree.
+ */
+ REJECT,
+
+ /**
+ * This result indicates that the tree visit should be terminated.
+ */
+ COMPLETE
+}
Index: jsf-ri/src/com/sun/faces/jsf-ri-config.xml
===================================================================
--- jsf-ri/src/com/sun/faces/jsf-ri-config.xml (revision 6051)
+++ jsf-ri/src/com/sun/faces/jsf-ri-config.xml (working copy)
 -53,6 +53,9 @@
     <exception-handler-factory>
       com.sun.faces.context.ExceptionHandlerFactoryImpl
     </exception-handler-factory>
+ <visit-context-factory>
+ com.sun.faces.component.visit.VisitContextFactoryImpl
+ </visit-context-factory>
     <faces-context-factory>
       com.sun.faces.context.FacesContextFactoryImpl
     </faces-context-factory>
Index: jsf-ri/src/com/sun/faces/lifecycle/RestoreViewPhase.java
===================================================================
--- jsf-ri/src/com/sun/faces/lifecycle/RestoreViewPhase.java (revision 6051)
+++ jsf-ri/src/com/sun/faces/lifecycle/RestoreViewPhase.java (working copy)
 -52,6 +52,8 @@
 import javax.faces.application.ViewHandler;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIViewRoot;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.component.visit.VisitResult;
 import javax.faces.context.FacesContext;
 import javax.faces.event.PhaseId;
 import javax.faces.event.PhaseListener;
 -63,7 +65,7 @@
 import com.sun.faces.util.FacesLogger;
 import com.sun.faces.util.MessageUtils;
 import com.sun.faces.util.Util;
-import javax.faces.component.ContextCallback;
+import javax.faces.component.visit.VisitCallback;
 import javax.faces.event.AbortProcessingException;
 import javax.faces.event.AfterAddToParentEvent;
 import javax.faces.event.AfterRestoreStateEvent;
 -137,12 +139,15 @@
             UIViewRoot root = facesContext.getViewRoot();
             final AfterRestoreStateEvent event = new AfterRestoreStateEvent(root);
             try {
- root.doTreeTraversal(facesContext, new ContextCallback() {
+ root.visitTree(VisitContext.createVisitContext(facesContext),
+ new VisitCallback() {
 
- public void invokeContextCallback(FacesContext context, UIComponent target) {
+ public VisitResult visit(VisitContext context, UIComponent target) {
                         event.setComponent(target);
                         target.processEvent(event);
+ return VisitResult.ACCEPT;
                     }
+
                 });
             } catch (AbortProcessingException e) {
                 facesContext.getApplication().publishEvent(ExceptionEvent.class, new ExceptionEventContext(facesContext, e));
Index: jsf-ri/src/com/sun/faces/component/visit/PartialVisitContext.java
===================================================================
--- jsf-ri/src/com/sun/faces/component/visit/PartialVisitContext.java (revision 0)
+++ jsf-ri/src/com/sun/faces/component/visit/PartialVisitContext.java (revision 0)
 -0,0 +1,311 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.faces.component.visit;
+
+import javax.faces.component.visit.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
+import javax.faces.component.NamingContainer;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ * <p class="changed_added_2_0">A VisitContext implementation that is
+ * used when performing a partial component tree visit.</p>
+ *
+ * RELEASE_PENDING
+ * @since 2.0
+ */
+public class PartialVisitContext extends VisitContext {
+
+ /**
+ * Creates a PartialVisitorContext instance.
+ * @param facesContext the FacesContext for the current request
+ * @param clientIds the client ids of the components to visit
+ * @throws NullPointerException if {_at_code facesContext}
+ * is {_at_code null}
+ */
+ public PartialVisitContext(FacesContext facesContext,
+ Collection<String> clientIds) {
+ this(facesContext, clientIds, null);
+ }
+
+ /**
+ * Creates a PartialVisitorContext instance with the specified hints.
+ * @param facesContext the FacesContext for the current request
+ * @param clientIds the client ids of the components to visit
+ * @param hints a the VisitHints for this visit
+ * @throws NullPointerException if {_at_code facesContext}
+ * is {_at_code null}
+ */
+ public PartialVisitContext(FacesContext facesContext,
+ Collection<String> clientIds,
+ Set<VisitHint> hints) {
+ if (facesContext == null)
+ throw new NullPointerException();
+
+ this.facesContext = facesContext;
+
+ // Copy the client ids into a HashSet to allow for quick lookups.
+ this.clientIds = (clientIds == null) ?
+ new HashSet<String>() :
+ new HashSet<String>(clientIds);
+
+ // Make another copy so we can easily track unvisited ids
+ this.unvisitedClientIds = new HashSet<String>(this.clientIds);
+
+ // Populate a collection of the ids (not client ids - just plain
+ // old ids) that we want to visit. This allows us to avoid extra
+ // UIComponent.getClientId() calls in PartialVisitContext.visit().
+ this.ids = populateIds(this.clientIds);
+
+ // Populate nested client ids needed by getIdsToVisit()
+ this.nestedClientIds = populateNestedClientIds(this.clientIds);
+
+ // Copy and store hints - ensure unmodifiable and non-empty
+ EnumSet hintsEnumSet = ((hints == null) || (hints.isEmpty())) ?
+ EnumSet.noneOf(VisitHint.class) :
+ EnumSet.copyOf(hints);
+
+ this.hints = Collections.unmodifiableSet(hintsEnumSet);
+ }
+
+ /**
+ * @see VisitContext#getFacesContext VisitContext.getFacesContext()
+ */
+ @Override
+ public FacesContext getFacesContext() {
+ return facesContext;
+ }
+
+ /**
+ * @see VisitContext#getHints VisitContext.getHints
+ */
+ @Override
+ public Set<VisitHint> getHints() {
+ return hints;
+ }
+
+ /**
+ * @see VisitContext#getIdsToVisit VisitContext.getIdsToVisit()
+ */
+ @Override
+ public Collection<String> getIdsToVisit(UIComponent component) {
+
+ // Make sure component is a NamingContainer
+ if (!(component instanceof NamingContainer)) {
+ throw new IllegalArgumentException("Component is not a NamingContainer: " + component);
+ }
+
+ String clientId = component.getClientId();
+ Collection<String> ids = nestedClientIds.get(clientId);
+
+ if (ids == null)
+ return Collections.emptyList();
+
+ return Collections.unmodifiableCollection(ids);
+ }
+
+ /**
+ * @see VisitContext#invokeVisitCallback VisitContext.invokeVisitCallback()
+ */
+ @Override
+ public VisitResult invokeVisitCallback(UIComponent component,
+ VisitCallback callback) {
+
+ // First sure that we should visit this component - ie.
+ // that this component is represented in our id set.
+ String clientId = getVisitId(component);
+
+ if (clientId == null) {
+ // Not visiting this component, but allow visit to
+ // continue into this subtree in case we've got
+ // visit targets there.
+ return VisitResult.ACCEPT;
+ }
+
+ // If we made it this far, the component matches one of
+ // client ids, so perform the visit.
+ VisitResult result = callback.visit(this, component);
+
+ // Remove the component from our "unvisited" collection
+ unvisitedClientIds.remove(clientId);
+
+ // If the unvisited collection is now empty, we are done.
+ // Return VisitResult.COMPLETE to terminate the visit.
+ if (unvisitedClientIds.isEmpty())
+ return VisitResult.COMPLETE;
+
+ // Otherwise, just return the callback's result
+ return result;
+ }
+
+ // Tests whether the specified component should be visited.
+ // If so, returns its client id. If not, returns null.
+ private String getVisitId(UIComponent component) {
+
+ // We first check to see whether the component's id
+ // is in our id collection. We do this before checking
+ // for the full client id because getting the full client id
+ // is more expensive than just getting the local id.
+ String id = component.getId();
+ if ((id != null) && !ids.contains(id))
+ return null;
+
+ // The id was a match - now check the client id.
+ // note that client id should never be null (should be
+ // generated even if id is null, so asserting this.)
+ String clientId = component.getClientId();
+ assert(clientId != null);
+
+ return clientIds.contains(clientId) ? clientId : null;
+ }
+
+ // Give a collection of client ids, return a collection of plain
+ // old ids
+ private Collection<String> populateIds(Collection<String> clientIds)
+ {
+ FacesContext facesContext = getFacesContext();
+ char separator = UINamingContainer.getSeparatorChar(facesContext);
+ HashSet<String> ids = new HashSet<String>(clientIds.size());
+
+ for (String clientId : clientIds)
+ {
+ int lastIndex = clientId.lastIndexOf(separator);
+
+ String id = null;
+
+ if (lastIndex < 0) {
+ id = clientId;
+ } else if (lastIndex < (clientId.length() - 1)) {
+ id = clientId.substring(lastIndex + 1);
+ }
+
+ if (id != null)
+ ids.add(id);
+ }
+
+ return ids;
+ }
+
+ // Populates the map that tracks nested ids underneath naming containers
+ private Map<String,Collection<String>> populateNestedClientIds(Collection<String> clientIds) {
+
+ FacesContext facesContext = getFacesContext();
+ char separator = UINamingContainer.getSeparatorChar(facesContext);
+
+ Map<String,Collection<String>> nestedClientIds =
+ new HashMap<String,Collection<String>>();
+
+ for (String clientId : clientIds)
+ populateNestedClientId(nestedClientIds, clientId, separator);
+
+ return nestedClientIds;
+ }
+
+ // Given a single client id, populate the map with all possible
+ // nested client ids
+ private void populateNestedClientId(Map<String, Collection<String>> nestedClientIds,
+ String clientId,
+ char separator) {
+
+
+ // Loop over the client id and find the substring corresponding to
+ // each ancestor NamingContainer client id. For each ancestor
+ // NamingContainer, add an entry into the map for the full client
+ // id.
+
+ int length = clientId.length();
+
+ for (int i = 0; i < length; i++) {
+
+ if (clientId.charAt(i) == separator) {
+
+ // We found an ancestor NamingContainer client id - add
+ // an entry to the map.
+ String namingContainerClientId = clientId.substring(0, i);
+
+ // Check to see whether we've already ids under this
+ // NamingContainer client id. If not, create the
+ // Collection for this NamingContainer client id and
+ // stash it away in our map
+ Collection<String> c = nestedClientIds.get(namingContainerClientId);
+
+ if (c == null) {
+ // TODO: smarter initial size?
+ c = new ArrayList<String>();
+ nestedClientIds.put(namingContainerClientId, c);
+ }
+
+ // Stash away the client id
+ c.add(clientId);
+ }
+ }
+ }
+
+
+ // The client ids to visit
+ private Collection<String> clientIds;
+
+ // The ids to visit
+ private Collection<String> ids;
+
+ // The client ids that have yet to be visited
+ private Collection<String> unvisitedClientIds;
+
+ // This map contains the information needed by getIdsToVisit().
+ // The keys in this map are NamingContainer client ids. The values
+ // are collections containing all of the client ids to visit within
+ // corresponding naming container.
+ private Map<String,Collection<String>> nestedClientIds;
+
+ // The FacesContext for this request
+ private FacesContext facesContext;
+
+ // Our visit hints
+ private Set<VisitHint> hints;
+}
Index: jsf-ri/src/com/sun/faces/component/visit/FullVisitContext.java
===================================================================
--- jsf-ri/src/com/sun/faces/component/visit/FullVisitContext.java (revision 0)
+++ jsf-ri/src/com/sun/faces/component/visit/FullVisitContext.java (revision 0)
 -0,0 +1,144 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.faces.component.visit;
+
+import javax.faces.component.visit.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import javax.faces.component.NamingContainer;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ * <p class="changed_added_2_0">A VisitContext implementation that is
+ * used when performing a full component tree visit.</p>
+ *
+ * RELEASE_PENDING
+ *
+ * @since 2.0
+ */
+public class FullVisitContext extends VisitContext {
+
+ /**
+ * Creates a FullVisitorContext instance.
+ * @param facesContext the FacesContext for the current request
+ * @throws NullPointerException if {_at_code facesContext}
+ * is {_at_code null}
+ */
+ public FullVisitContext(FacesContext facesContext) {
+ this(facesContext, null);
+ }
+
+ /**
+ * Creates a FullVisitorContext instance with the specified
+ * hints.
+ *
+ * @param facesContext the FacesContext for the current request
+ * @param hints a the VisitHints for this visit
+ * @throws NullPointerException if {_at_code facesContext}
+ * is {_at_code null}
+ */
+ public FullVisitContext(FacesContext facesContext,
+ Set<VisitHint> hints) {
+
+ if (facesContext == null)
+ throw new NullPointerException();
+
+ this.facesContext = facesContext;
+
+ // Copy and store hints - ensure unmodifiable and non-empty
+ EnumSet hintsEnumSet = ((hints == null) || (hints.isEmpty())) ?
+ EnumSet.noneOf(VisitHint.class) :
+ EnumSet.copyOf(hints);
+
+ this.hints = Collections.unmodifiableSet(hintsEnumSet);
+ }
+
+ /**
+ * @see VisitContext#getFacesContext VisitContext.getFacesContext()
+ */
+ @Override
+ public FacesContext getFacesContext() {
+ return facesContext;
+ }
+
+ /**
+ * @see VisitContext#getIdsToVisit VisitContext.getIdsToVisit()
+ */
+ @Override
+ public Collection<String> getIdsToVisit(UIComponent component) {
+
+ // Make sure component is a NamingContainer
+ if (!(component instanceof NamingContainer)) {
+ throw new IllegalArgumentException("Component is not a NamingContainer: " + component);
+ }
+
+ // We always visits all ids
+ return ALL_IDS;
+ }
+
+ /**
+ * @see VisitContext#getHints VisitContext.getHints
+ */
+ @Override
+ public Set<VisitHint> getHints() {
+ return hints;
+ }
+
+ /**
+ * @see VisitContext#invokeVisitCallback VisitContext.invokeVisitCallback()
+ */
+ @Override
+ public VisitResult invokeVisitCallback(UIComponent component,
+ VisitCallback callback) {
+
+ // Nothing interesting here - just invoke the callback.
+ // (PartialVisitContext.invokeVisitCallback() does all of the
+ // interesting work.)
+ return callback.visit(this, component);
+ }
+
+ // The FacesContext for this request
+ private FacesContext facesContext;
+
+ // Our visit hints
+ private Set<VisitHint> hints;
+}
Index: jsf-ri/src/com/sun/faces/component/visit/VisitContextFactoryImpl.java
===================================================================
--- jsf-ri/src/com/sun/faces/component/visit/VisitContextFactoryImpl.java (revision 0)
+++ jsf-ri/src/com/sun/faces/component/visit/VisitContextFactoryImpl.java (revision 0)
 -0,0 +1,69 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.faces.component.visit;
+
+import java.util.Collection;
+import java.util.Set;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.component.visit.VisitContextFactory;
+import javax.faces.component.visit.VisitHint;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ */
+public class VisitContextFactoryImpl extends VisitContextFactory {
+
+ @Override
+ public VisitContext getVisitContext(FacesContext context,
+ Collection<String> ids,
+ Set<VisitHint> hints) {
+ VisitContext result = null;
+
+ if (null == ids || ids.isEmpty()) {
+ result = new FullVisitContext(context, hints);
+ }
+ else {
+ result = new PartialVisitContext(context, ids, hints);
+ }
+
+ return result;
+ }
+
+
+
+}
Index: jsf-ri/src/com/sun/faces/config/processor/FactoryConfigProcessor.java
===================================================================
--- jsf-ri/src/com/sun/faces/config/processor/FactoryConfigProcessor.java (revision 6051)
+++ jsf-ri/src/com/sun/faces/config/processor/FactoryConfigProcessor.java (working copy)
 -81,6 +81,11 @@
     private static final String EXCEPTION_HANDLER_FACTORY = "exception-handler-factory";
 
     /**
+ * <code>/faces-config/factory/visit-context-factory</code>
+ */
+ private static final String VISIT_CONTEXT_FACTORY = "visit-context-factory";
+
+ /**
      * <code>/faces-config/factory/page-declaration-language-factory</code>
      */
     private static final String PAGE_DECLARATION_LANGUAGE_FACTORY = "page-declaration-language-factory";
 -106,6 +111,7 @@
      */
     private static final String[] FACTORY_NAMES = {
           FactoryFinder.APPLICATION_FACTORY,
+ FactoryFinder.VISIT_CONTEXT_FACTORY,
           FactoryFinder.EXCEPTION_HANDLER_FACTORY,
           FactoryFinder.FACES_CONTEXT_FACTORY,
           FactoryFinder.LIFECYCLE_FACTORY,
 -193,6 +199,9 @@
                 } else if (EXCEPTION_HANDLER_FACTORY.equals(n.getLocalName())) {
                     setFactory(FactoryFinder.EXCEPTION_HANDLER_FACTORY,
                                getNodeText(n));
+ } else if (VISIT_CONTEXT_FACTORY.equals(n.getLocalName())) {
+ setFactory(FactoryFinder.VISIT_CONTEXT_FACTORY,
+ getNodeText(n));
                 } else if (LIFECYCLE_FACTORY.equals(n.getLocalName())) {
                     setFactory(FactoryFinder.LIFECYCLE_FACTORY,
                                getNodeText(n));
Index: jsf-demo/tree-visit/src/main/java/treevisit/Bean.java
===================================================================
--- jsf-demo/tree-visit/src/main/java/treevisit/Bean.java (revision 0)
+++ jsf-demo/tree-visit/src/main/java/treevisit/Bean.java (revision 0)
 -0,0 +1,210 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package treevisit;
+
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+
+import java.util.logging.Logger;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.component.visit.VisitHint;
+import javax.faces.component.visit.VisitResult;
+
+import javax.faces.event.ActionEvent;
+import javax.faces.model.SelectItem;
+
+/**
+ * <p>This bean has the methods that are used to illustrate
+ * the tree visitor API</p>
+ *
+ */
+
+public class Bean {
+
+ private static final Logger LOGGER = Logger.getLogger("treevisit");
+
+ //
+ // Instance Variables
+ //
+
+ // List of SelectItems representing all client ids on the page
+ private List<SelectItem> items;
+
+ // List of ids selected by the end user
+ private List<String> selectedIds;
+
+ // List of ids visited by our partial tree visit.
+ private List<String> visitedIds;
+
+ // Flag indicating whether or not we should visit rendered
+ // subtrees only.
+ private boolean visitRendered;
+
+ //
+ // Constructors
+ //
+
+ public Bean() {
+ loadItems();
+ }
+
+ // Returns a list containing a SelectItem corresponding to
+ // every component client id in this component tree.
+ public List<SelectItem> getItems() {
+ return items;
+ }
+
+ // Returns the list of ids to visit
+ public List<String> getSelectedIds() {
+ return selectedIds;
+ }
+
+ // Sets the list of ids to visit
+ public void setSelectedIds(List<String> selectedIds) {
+ this.selectedIds = selectedIds;
+ }
+
+ // Returns the list of ids that were visited
+ public List<String> getVisitedIds() {
+ return visitedIds;
+ }
+
+ // Returns whether we should visit rendered components only
+ public boolean getVisitRendered() {
+ return visitRendered;
+ }
+
+ // Sets whether we shoudl visit rendered components only
+ public void setVisitRendered(boolean visitRendered) {
+ this.visitRendered = visitRendered;
+ }
+
+
+ // ActionListener that triggers a partial visit of the
+ // selected ids.
+ public void visit(ActionEvent ae) {
+
+ // To perform a tree visit, we need three things:
+ // 1. A VisitContext
+ // 2. A VisitCallback
+ // 3. A component at which to start the visit.
+
+ // Get our VisitContext. We use PartialVisitContext since we
+ // we only want to visit a subset of the component tree.
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ EnumSet<VisitHint> hints = getVisitRendered() ?
+ EnumSet.of(VisitHint.VISIT_RENDERED) :
+ null;
+ VisitContext visitContext =
+ VisitContext.createVisitContext(facesContext, getSelectedIds(), hints);
+
+ // Use CollectIdsVisitCallback to collect up visited ids
+ CollectIdsVisitCallback visitCallback = new CollectIdsVisitCallback();
+
+ // Start the visit at the view root
+ UIComponent viewRoot = facesContext.getViewRoot();
+
+ // Do the visit
+ viewRoot.visitTree(visitContext, visitCallback);
+
+ // And stash away the results
+ visitedIds = visitCallback.getVisitedIds();
+ }
+
+ // Loads the items - ie. the list of client ids for
+ // all components in this document.
+ private void loadItems() {
+
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ assert(facesContext != null);
+
+ // We collect ids by performing a full tree visit. So, we
+ // need a VisitContext, a VisitCallback, and a component to
+ // initiate the visit on.
+ VisitContext visitContext = VisitContext.createVisitContext(facesContext, null, null);
+ CollectIdsVisitCallback visitCallback = new CollectIdsVisitCallback();
+ UIComponent viewRoot = facesContext.getViewRoot();
+
+ viewRoot.visitTree(visitContext, visitCallback);
+
+ List<String> ids = visitCallback.getVisitedIds();
+ List<SelectItem> selectItems = new ArrayList<SelectItem>(ids.size());
+
+ for (String id : ids) {
+ selectItems.add(new SelectItem(id));
+ }
+
+ this.items = selectItems;
+ }
+
+
+ // Callback class for collecting all ids
+ static private class CollectIdsVisitCallback implements VisitCallback {
+
+ // Collect ids in the list
+ private List<String> ids = new ArrayList<String>();
+
+ // Performs the visit
+ public VisitResult visit(VisitContext context, UIComponent component) {
+
+ String clientId = component.getClientId();
+
+ // For the moment let's blow off any top-level auto-generated
+ // ids. Facelets generates several UIInstructions components
+ // which seem to be removed from the component tree at some point.
+ // These might cause some confusion, so excluding this for our list.
+
+ if (!clientId.startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
+ ids.add(clientId);
+
+ return VisitResult.ACCEPT;
+ }
+
+ // Returns the collected ids
+ public List<String> getVisitedIds() {
+ return ids;
+ }
+ }
+}
Index: jsf-demo/tree-visit/src/main/webapp/home.xhtml
===================================================================
--- jsf-demo/tree-visit/src/main/webapp/home.xhtml (revision 0)
+++ jsf-demo/tree-visit/src/main/webapp/home.xhtml (revision 0)
 -0,0 +1,132 @@
+<!--
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets">
+<f:view contentType="text/html"/>
+
+<!--
+ TODO: Add transient components to test VisitHint.VISIT_TRANSIENT.
+ TODO: Add UIData component to test VisitHint.VISIT_ITERATED.
+
+-->
+<h:head id="head">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>Tree Visit</title>
+</h:head>
+
+<h:body id="body">
+
+ <h:form id="form">
+ <h:panelGrid styleClass="title-panel" id="titleGrid">
+ <h:outputText value="t r e e V i s i t" styleClass="title-panel-text"
+ id="title"/>
+ <h:outputText value="Powered By JavaServer Faces 2.0 "
+ styleClass="title-panel-subtext"
+ id="subTitle"/>
+ </h:panelGrid>
+
+ <h:panelGrid id="mainGrid">
+ <h:outputText value="Select component ids from the listbox below and then click the 'Visit' button to perform a tree visit that includes the specified components. The ids of the components that are reached during the tree visit are displayed below."
+ id="instructions"/>
+
+ <h:outputLabel for="list" value="Components To Visit"
+ styleClass="subtitle"
+ id="componentsListLabel"/>
+
+ <h:selectManyListbox value="#{bean.selectedIds}" id="componentsList" size="10">
+ <f:selectItems value="#{bean.items}"/>
+ </h:selectManyListbox>
+
+ <h:panelGroup id="visitRenderedGroup">
+ <h:selectBooleanCheckbox value="#{bean.visitRendered}"
+ id="visitRenderedCheckbox"/>
+
+ <h:outputLabel value="Visit rendered components only"
+ for="visitRenderedCheckbox"
+ id="visitRenderedLabel"/>
+ </h:panelGroup>
+
+ <h:commandButton value="visit" actionListener="#{bean.visit}"
+ id="visitButton">
+ <f:ajax execute="form" render="form:visitedTable"/>
+ </h:commandButton>
+
+ <h:outputText value="Some NamingContainer Components" id="namingContainers"
+ styleClass="subtitle"/>
+
+ <h:panelGrid id="subviews">
+ <f:subview id="subviewA">
+ <h:panelGroup id="groupA">
+ <h:outputText value="This is in subview A" id="textA"/>
+ </h:panelGroup>
+ </f:subview>
+
+ <f:subview id="subviewB">
+ <h:panelGroup id="groupB">
+ <h:outputText value="This is in subview B" id="textB"/>
+ </h:panelGroup>
+ </f:subview>
+
+ <f:subview id="nonRenderedSubview" rendered="false">
+ <h:panelGroup id="nonRenderedGroup">
+ <h:outputText value="This is in subview B"
+ id="nonRenderedText"/>
+ </h:panelGroup>
+ </f:subview>
+
+ </h:panelGrid>
+
+ <h:dataTable value="#{bean.visitedIds}" var="visitedId" id="visitedTable">
+ <h:column id="visitedColumn">
+ <f:facet name="header">
+ <h:outputText value="Visited Components" id="visitedColumnHeader"
+ styleClass="subtitle"/>
+ </f:facet>
+
+ <h:outputText value="#{visitedId}" id="visitedText"/>
+ </h:column>
+ </h:dataTable>
+ </h:panelGrid>
+
+ <h:outputStylesheet name="stylesheet.css"/>
+ </h:form>
+
+</h:body>
+
+</html>
Index: jsf-demo/tree-visit/src/main/webapp/WEB-INF/faces-config.xml
===================================================================
--- jsf-demo/tree-visit/src/main/webapp/WEB-INF/faces-config.xml (revision 0)
+++ jsf-demo/tree-visit/src/main/webapp/WEB-INF/faces-config.xml (revision 0)
 -0,0 +1,57 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<!--
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+-->
+
+<!-- =========== FULL CONFIGURATION FILE ================================== -->
+
+<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
+ 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_2_0.xsd"
+ version="2.0">
+
+ <!-- managed beans -->
+
+ <managed-bean>
+ <description>
+ The main backing file mean
+ </description>
+ <managed-bean-name>bean</managed-bean-name>
+ <managed-bean-class>treevisit.Bean</managed-bean-class>
+ <managed-bean-scope>session</managed-bean-scope>
+ </managed-bean>
+
+</faces-config>
Index: jsf-demo/tree-visit/src/main/webapp/WEB-INF/web.xml
===================================================================
--- jsf-demo/tree-visit/src/main/webapp/WEB-INF/web.xml (revision 0)
+++ jsf-demo/tree-visit/src/main/webapp/WEB-INF/web.xml (revision 0)
 -0,0 +1,95 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<!--
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+-->
+
+<web-app version="2.5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ 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-app_2_5.xsd">
+
+ <display-name></display-name>
+ <description></description>
+
+ <context-param>
+ <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
+ <param-value>server</param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
+ <param-value>.xhtml</param-value>
+ </context-param>
+ <context-param>
+ <param-name>facelets.DEVELOPMENT</param-name>
+ <param-value>true</param-value>
+ </context-param>
+
+ <context-param>
+ <description>
+ Set this flag to true if you want the JavaServer Faces
+ Reference Implementation to validate the XML in your
+ faces-config.xml resources against the DTD. Default
+ value is false.
+ </description>
+ <param-name>com.sun.faces.validateXml</param-name>
+ <param-value>true</param-value>
+ </context-param>
+
+ <!-- Faces Servlet -->
+ <servlet>
+ <servlet-name>Faces Servlet</servlet-name>
+ <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+
+ <!-- Faces Servlet Mapping -->
+ <!--
+
+ This mapping identifies a jsp page as having JSF content. If a
+ request comes to the server for foo.faces, the container will
+ send the request to the FacesServlet, which will expect a
+ corresponding foo.jsp page to exist containing the content.
+
+ -->
+ <servlet-mapping>
+ <servlet-name>Faces Servlet</servlet-name>
+ <url-pattern>/faces/*</url-pattern>
+ <url-pattern>*.jsf</url-pattern>
+ </servlet-mapping>
+
+</web-app>
Index: jsf-demo/tree-visit/src/main/webapp/index.html
===================================================================
--- jsf-demo/tree-visit/src/main/webapp/index.html (revision 0)
+++ jsf-demo/tree-visit/src/main/webapp/index.html (revision 0)
 -0,0 +1,41 @@
+<!--
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+-->
+
+<html>
+<header>
+<meta http-equiv="Refresh" content="0;url=home.jsf">
+</header>
+</html>
Index: jsf-demo/tree-visit/src/main/webapp/resources/stylesheet.css
===================================================================
--- jsf-demo/tree-visit/src/main/webapp/resources/stylesheet.css (revision 0)
+++ jsf-demo/tree-visit/src/main/webapp/resources/stylesheet.css (revision 0)
 -0,0 +1,244 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+.title-panel {
+ background-image: url(redwaveani.gif.jsf);
+ height: 80px;
+ width: 1380;
+}
+
+.title-panel-text {
+ color: white;
+ font-family: 'Georgia','Times New Roman','times',serif;
+ font-size: 24px;
+ font-weight: bold;
+}
+
+.title-panel-subtext {
+ color: white;
+ font-family: 'Georgia','Times New Roman','times',serif;
+ font-size: 14px;
+ font-style: italic
+}
+
+body {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px;
+}
+
+td {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px;
+}
+
+th {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px;
+}
+
+.bodystyle {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px;
+}
+
+.small {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 9px;
+}
+
+.medium {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px;
+}
+
+.maintitle {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 14px;
+ color: #330066;
+}
+
+.subtitle {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ font-weight: bold;
+ color: #93B629;
+}
+
+.subtitlebig {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16px;
+ color: #93B629;
+ padding-top: 10;
+ padding-bottom: 10;
+}
+
+.big {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16px;
+}
+
+.xbig {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 24px;
+}
+
+.expanded {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ line-height: 24px;
+ letter-spacing: 2px;
+}
+
+.justified {
+ font-family: Arial, Helvetica, sans-serif;
+ text-align: justify;
+}
+
+.footer {
+ font-family: "Times New Roman", Times, serif;
+ font-size: 9px;
+ color: #999999;
+}
+
+.box1 {
+ padding: 3px;
+ border-width: medium;
+ border-style: solid;
+ border-color: #CCCCCC #666666 #666666 #CCCCCC;
+}
+
+.box2 {
+ font-style: italic;
+ word-spacing: 2pt;
+ padding: 3px;
+ border: 1px solid;
+}
+
+.align-left {
+ text-align: left;
+}
+
+.control-panel-border {
+ border: 5px outset red;
+}
+
+.x-button-border {
+ border: 3px outset blue;
+}
+
+.o-button-border {
+ border: 3px outset red;
+}
+
+.win-button-border {
+ border: 3px outset yellow;
+}
+
+.execute {
+ background-color: #bfefff;
+}
+
+.render {
+ border: 3px outset red;
+}
+
+.initial-render {
+ border: 3px outset green;
+}
+
+.execute-render {
+ border: 3px outset red;
+ background-color: #bfefff;
+}
+
+.keytitle {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16px;
+ color: #330066;
+}
+
+.options-prompt {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16px;
+ color: blue;
+}
+.options {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16px;
+ color: red;
+}
+
+
+.panel-border {
+ border: 2px outset blue;
+ background-color: #c1cdcd;
+}
+
+.panel-background {
+ background-color: #7171A5;
+ border: 5px outset #71A5A5;
+ border-collapse: collapse;
+ font-family: sans-serif;
+ font-size: 14pt;
+ padding: 10px;
+}
+
+.package-selected {
+ background-color: #93B629;
+}
+
+.package-unselected {
+ background-color: #C0C0C0;
+}
+
+.option-unselected {
+ background-color: #FFFFFF;
+}
+
+.top-table {
+ padding: 0;
+ border: 0;
+ width: 660px;
+}
+
+.storeFrontCar {
+ padding: 0;
+ border: 0;
+}
+
+.validationMessage {
+ color: red;
+}
Index: jsf-demo/tree-visit/src/main/webapp/resources/redwaveani.gif
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: jsf-demo/tree-visit/src/main/webapp/resources/redwaveani.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Index: jsf-demo/tree-visit/pom.xml
===================================================================
--- jsf-demo/tree-visit/pom.xml (revision 0)
+++ jsf-demo/tree-visit/pom.xml (revision 0)
 -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.sun.faces.extensions</groupId>
+ <artifactId>tree-visit</artifactId>
+ <packaging>war</packaging>
+ <name>tree-visit</name>
+ <url>https://mojarra.dev.java.net/</url>
+ <description>Tree Visit JSF Demo</description>
+ <version>0.1</version>
+
+ <scm>
+ <connection>scm:svn:http://jsf-extensions.dev.java.net/svn/jsf-extensions/trunk</connection>
+ <developerConnection>scm:svn:https://jsf-extensions.dev.java.net/svn/jsf-extensions/trunk</developerConnection>
+ <url>https://jsf-extensions.dev.java.net/source/browse/jsf-extensions/</url>
+ </scm>
+
+ <build>
+ <defaultGoal>install</defaultGoal>
+ <sourceDirectory>src/main/java</sourceDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <targetPath>resources</targetPath>
+ <includes>
+ <include>*.taglib.xml</include>
+ <include>faces-config.xml</include>
+ <include>*.js</include>
+ </includes>
+ </resource>
+ </resources>
+ <finalName>tree-visit</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>source</id>
+ <phase>generate-resources</phase>
+ <configuration>
+ <tasks>
+ <echo message="Copying properties files to WEB-INF/classes" />
+ <copy todir="target/${project.build.finalName}/WEB-INF/classes">
+ <fileset dir="src/main/java">
+ <include name="**/*.properties" />
+ </fileset>
+ </copy>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>RELEASE</version>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+
+ <repositories>
+ <repository>
+ <snapshots />
+ <id>codecaus</id>
+ <name>codehaus</name>
+ <url>http://repository.codehaus.org</url>
+ </repository>
+ <repository>
+ <snapshots />
+ <id>java.net</id>
+ <name>Java.net Maven 1.x Repository for external projects</name>
+ <url>https://maven-repository.dev.java.net/nonav/repository</url>
+ <layout>legacy</layout>
+ </repository>
+ <repository>
+ <snapshots />
+ <id>java.net.shared</id>
+ <name>Java.net Maven 1.x Repository for glassfish dependencies</name>
+ <url>http://download.java.net/javaee5/external/shared</url>
+ <layout>legacy</layout>
+ </repository>
+ <repository>
+ <snapshots />
+ <id>ibiblio</id>
+ <url>http://www.ibiblio.org/maven2/</url>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.sun.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javaee</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>5</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <reportSets><reportSet /></reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+
+</project>
Index: jsf-demo/tree-visit/build.xml
===================================================================
--- jsf-demo/tree-visit/build.xml (revision 0)
+++ jsf-demo/tree-visit/build.xml (revision 0)
 -0,0 +1,126 @@
+<!--
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the GNU
+ General Public License Version 2 only ("GPL") or the Common Development
+ and Distribution License("CDDL") (collectively, the "License"). You
+ may not use this file except in compliance with the License. You can obtain
+ a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ language governing permissions and limitations under the License.
+
+ When distributing the software, include this License Header Notice in each
+ file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the GPL Version 2 section of the License file that
+ accompanied this code. If applicable, add the following below the License
+ Header, with the fields enclosed by brackets [] replaced by your own
+ identifying information: "Portions Copyrighted [year]
+ [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the CDDL or
+ only the GPL Version 2, indicate your decision by adding "[Contributor]
+ elects to include this software in this distribution under the [CDDL or GPL
+ Version 2] license." If you don't indicate a single choice of license, a
+ recipient has the option to distribute your version of this file under
+ either the CDDL, the GPL Version 2 or to extend the choice of license to
+ its licensees as provided above. However, if you add GPL Version 2 code
+ and therefore, elected the GPL Version 2 license, then the option applies
+ only if the new code is made subject to such option by the copyright
+ holder.
+-->
+
+<project name="tree-visit" default="build" basedir=".">
+
+
+ <property file="${user.home}/build.properties"/>
+ <property file="../../build.properties"/>
+ <import file="${jsf.build.home}/common/ant/common.xml"/>
+
+ <!-- Configure the context path for this application -->
+ <property name="context.path" value="/tree-visit"/>
+ <property name="example" value="tree-visit"/>
+ <property name="build" value="${basedir}/build"/>
+
+ <path id="classpath">
+ <pathelement location="${jsf-api.jar}"/>
+ <pathelement location="${jsf-impl.jar}"/>
+ <path refid="compile.classpath"/>
+ </path>
+
+ <target name="init" depends="check.changes">
+ <tstamp/>
+ </target>
+
+ <target name="check.changes">
+ <uptodate property="skip.build"
+ targetfile="${build}/last-build">
+ <srcfiles dir="${basedir}">
+ <include name="src/**/*.*"/>
+ </srcfiles>
+ </uptodate>
+ </target>
+
+ <target name="clean">
+ <delete dir="${build}"/>
+ </target>
+
+ <target name="prepare" depends="init"
+ description="Create build directories.">
+ <mkdir dir="${build}/${example}"/>
+ <mkdir dir="${build}/${example}/WEB-INF"/>
+ <mkdir dir="${build}/${example}/WEB-INF/classes"/>
+ </target>
+
+
+ <target name="build" unless="skip.build" depends="prepare"
+ description="Compile Java files and copy static files.">
+ <touch file="${build}/last-build"/>
+ <jsf.javac srcdir="src/main/java"
+ destdir="${build}/${example}/WEB-INF/classes">
+ <classpath>
+ <path refid="classpath"/>
+ </classpath>
+ </jsf.javac>
+ <copy todir="${build}/${example}/WEB-INF">
+ <fileset dir="src/main/webapp/WEB-INF">
+ <include name="*.tld"/>
+ <include name="*.xml"/>
+ </fileset>
+ </copy>
+
+ <copy todir="${build}/${example}/">
+ <fileset dir="src/main/webapp">
+ <include name="*.xhtml"/>
+ <include name="*.html"/>
+ <include name="*.gif"/>
+ <include name="*.jpg"/>
+ <include name="*.jsp"/>
+ <include name="*.xml"/>
+ </fileset>
+ </copy>
+ <copy todir="${build}/${example}/WEB-INF/classes/treevisit">
+ <fileset dir="src/main/java/treevisit">
+ <include name="*properties"/>
+ </fileset>
+ </copy>
+
+ <copy todir="${build}/${example}/resources">
+ <fileset dir="src/main/webapp/resources"/>
+ </copy>
+
+ <jsf.war basedir="${build}"
+ archive-name="${example}"
+ webxml="${build}/${example}/WEB-INF/web.xml">
+ <archive-elements>
+ <zipfileset dir="${build}/${example}"/>
+ </archive-elements>
+ </jsf.war>
+ </target>
+
+</project>
+

-- 
| ed.burns_at_sun.com  | office: 408 884 9519 OR x31640
| homepage:         | http://ridingthecrest.com/