Author: knopp
Date: Wed Jul 25 06:03:42 2007
New Revision: 559446

URL: http://svn.apache.org/viewvc?view=rev&rev=559446
Log:
WICKET-627 Can't visit components in a ListView before they're rendered.

Modified:
    
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java
    
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
    
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Page.java
    
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ajax/AjaxRequestTarget.java
    
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/list/ListView.java
    
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/tree/AbstractTree.java

Modified: 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java?view=diff&rev=559446&r1=559445&r2=559446
==============================================================================
--- 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java
 (original)
+++ 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java
 Wed Jul 25 06:03:42 2007
@@ -652,6 +652,13 @@
        protected static final int FLAG_RESERVED8 = 0x80000;
 
        /**
+        * Flag that makes we are in before-render callback phase Set after
+        * component.onBeforeRender is invoked (right before invoking 
beforeRender
+        * on children)
+        */
+       static final int FLAG_PREPARED_FOR_RENDER = 0x4000000;
+
+       /**
         * Meta data key for line precise error logging for the moment of 
addition.
         * Made package private for access in [EMAIL PROTECTED] 
MarkupContainer} and
         * [EMAIL PROTECTED] Page}
@@ -670,6 +677,7 @@
                private static final long serialVersionUID = 1L;
        };
 
+
        static final int FLAG_ATTACH_SUPER_CALL_VERIFIED = 0x10000000;
 
        static final int FLAG_ATTACHED = 0x20000000;
@@ -839,9 +847,10 @@
         */
        public final void beforeRender()
        {
-               if (!getFlag(FLAG_RENDERING))
+               if (!getFlag(FLAG_RENDERING) && 
!getFlag(FLAG_PREPARED_FOR_RENDER))
                {
                        setFlag(FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED, 
false);
+
                        onBeforeRender();
                        
getApplication().notifyComponentOnBeforeRenderListeners(this);
                        if (!getFlag(FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED))
@@ -851,12 +860,40 @@
                                                getClass().getName() +
                                                " has not called 
super.onBeforeRender() in the override of onBeforeRender() method");
                        }
-                       onBeforeRenderChildren();
-                       setFlag(FLAG_RENDERING, true);
                }
        }
 
        /**
+        * Prepares the component and it's children for rendering. On whole page
+        * render this method must be called on the page. On AJAX request, this
+        * method must be called on updated component.
+        */
+       public void prepareForRender()
+       {
+               beforeRender();
+               markRendering();
+       }
+
+       /**
+        * Sets the RENDERING flag on component and it's children.
+        */
+       public final void markRendering()
+       {
+               internalMarkRendering();
+       }
+
+       boolean isPreparedForRender()
+       {
+               return getFlag(FLAG_PREPARED_FOR_RENDER);
+       }
+
+       void internalMarkRendering()
+       {
+               setFlag(FLAG_PREPARED_FOR_RENDER, false);
+               setFlag(FLAG_RENDERING, true);
+       }
+
+       /**
         * Redirects to any intercept page previously specified by a call to
         * redirectToInterceptPage.
         * 
@@ -1219,7 +1256,8 @@
                        // if not in the markup, generate one
 
                        markupId = getId() + page.getAutoIndex();
-                       // make sure id is compliant with w3c requirements 
(starts with a letter)
+                       // make sure id is compliant with w3c requirements 
(starts with a
+                       // letter)
                        char c = markupId.charAt(0);
                        if (!Character.isLetter(c))
                        {
@@ -1955,6 +1993,8 @@
         */
        public final void render(final MarkupStream markupStream)
        {
+               markRendering();
+
                setMarkupStream(markupStream);
                setFlag(FLAG_HAS_BEEN_RENDERED, true);
 
@@ -2067,6 +2107,7 @@
                                parent.setMarkupStream(markupStream);
 
                                beforeRender();
+                               markRendering();
                                // check authorization
                                // first the component itself
                                // (after attach as otherwise list views etc 
wont work)
@@ -3250,6 +3291,8 @@
         */
        protected void onBeforeRender()
        {
+               setFlag(FLAG_PREPARED_FOR_RENDER, true);
+               onBeforeRenderChildren();
                setFlag(FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED, true);
        }
 

Modified: 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java?view=diff&rev=559446&r1=559445&r2=559446
==============================================================================
--- 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
 (original)
+++ 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/MarkupContainer.java
 Wed Jul 25 06:03:42 2007
@@ -223,6 +223,7 @@
                }
                add(component);
                component.beforeRender();
+               component.markRendering();
                if (markupStream == null)
                {
                        component.render();
@@ -924,6 +925,14 @@
                {
                        page.componentAdded(component);
                }
+
+               // if the PREPARED_FOR_RENDER flag is set, we have alrady called
+               // beforeRender on this
+               // component's children. So we need to initialize the newly 
added one
+               if (isPreparedForRender())
+               {
+                       component.beforeRender();
+               }
        }
 
        /**
@@ -1465,20 +1474,51 @@
                super.detachChildren();
        }
 
+       void internalMarkRendering()
+       {
+               super.internalMarkRendering();
+               final int size = children_size();
+               for (int i = 0; i < size; i++)
+               {
+                       final Component child = children_get(i);
+                       child.internalMarkRendering();
+               }
+       }
+
+       private Component[] copyChildren()
+       {
+               int size = children_size();
+               Component result[] = new Component[size];
+               for (int i = 0; i < size; ++i)
+               {
+                       result[i] = children_get(i);
+               }
+               return result;
+       }
+
        void onBeforeRenderChildren()
        {
                super.onBeforeRenderChildren();
+
+               // We need to copy the children list because the children 
components can
+               // modify the hierarchy in their onBeforeRender.
+               Component[] children = copyChildren();
                try
                {
                        // Loop through child components
-                       final int size = children_size();
-                       for (int i = 0; i < size; i++)
+                       for (int i = 0; i < children.length; i++)
                        {
                                // Get next child
-                               final Component child = children_get(i);
+                               final Component child = children[i];
 
                                // Call begin request on the child
-                               child.beforeRender();
+                               // We need to check whether the child's wasn't 
removed from the
+                               // component in the meanwhile (e.g. from 
another's child
+                               // onBeforeRender)
+                               if (child.getParent() == this)
+                               {
+                                       child.beforeRender();
+                               }
                        }
                }
                catch (RuntimeException ex)

Modified: 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Page.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Page.java?view=diff&rev=559446&r1=559445&r2=559446
==============================================================================
--- 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Page.java 
(original)
+++ 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Page.java 
Wed Jul 25 06:03:42 2007
@@ -366,10 +366,8 @@
                        }
                        if (renderedComponents.add(component) == false)
                        {
-                               throw new MarkupException(
-                                               "The component "
-                                                               + component
-                                                               + " has the 
same wicket:id as another component already added at the same level");
+                               throw new MarkupException("The component " + 
component +
+                                               " has the same wicket:id as 
another component already added at the same level");
                        }
                        if (log.isDebugEnabled())
                        {
@@ -576,8 +574,8 @@
                        }
                        else
                        {
-                               log.info("No version manager available to 
retrieve requested versionNumber "
-                                               + versionNumber);
+                               log.info("No version manager available to 
retrieve requested versionNumber " +
+                                               versionNumber);
                                return null;
                        }
                }
@@ -605,8 +603,8 @@
                                }
 
                                // If we went all the way back to the original 
page
-                               if (page != null && 
page.getCurrentVersionNumber() == 0
-                                               && page.getAjaxVersionNumber() 
== 0)
+                               if (page != null && 
page.getCurrentVersionNumber() == 0 &&
+                                               page.getAjaxVersionNumber() == 
0)
                                {
                                        // remove version info
                                        page.versionManager = null;
@@ -646,8 +644,8 @@
                                {
                                        levels++;
                                }
-                               buffer.append(StringValue.repeat(levels, "      
") + component.getPageRelativePath()
-                                               + ":" + 
Classes.simpleName(component.getClass()));
+                               buffer.append(StringValue.repeat(levels, "      
") + component.getPageRelativePath() +
+                                               ":" + 
Classes.simpleName(component.getClass()));
                                return null;
                        }
                });
@@ -746,8 +744,8 @@
                        stateless = Boolean.FALSE;
                        if (getStatelessHint())
                        {
-                               log.warn("Page '" + this + "' is not stateless 
because it is not bookmarkable, "
-                                               + "but the stateless hint is 
set to true!");
+                               log.warn("Page '" + this + "' is not stateless 
because it is not bookmarkable, " +
+                                               "but the stateless hint is set 
to true!");
                        }
                }
 
@@ -778,8 +776,8 @@
 
                        if (!stateless.booleanValue() && getStatelessHint())
                        {
-                               log.warn("Page '" + this + "' is not stateless 
because of '" + returnArray[0]
-                                               + "' but the stateless hint is 
set to true!");
+                               log.warn("Page '" + this + "' is not stateless 
because of '" + returnArray[0] +
+                                               "' but the stateless hint is 
set to true!");
                        }
                }
 
@@ -813,8 +811,8 @@
                // Check that formClass is an instanceof Form
                if (!Form.class.isAssignableFrom(formClass))
                {
-                       throw new WicketRuntimeException("Form class " + 
formClass.getName()
-                                       + " is not a subclass of Form");
+                       throw new WicketRuntimeException("Form class " + 
formClass.getName() +
+                                       " is not a subclass of Form");
                }
 
                // Visit all children which are an instance of formClass
@@ -882,7 +880,7 @@
 
                try
                {
-                       beforeRender();
+                       prepareForRender();
                }
                catch (RuntimeException e)
                {
@@ -1002,8 +1000,8 @@
                if (value && !isBookmarkable())
                {
                        throw new WicketRuntimeException(
-                                       "Can't set stateless hint to true on a 
page when the page is not bookmarkable, page: "
-                                                       + this);
+                                       "Can't set stateless hint to true on a 
page when the page is not bookmarkable, page: " +
+                                                       this);
                }
                setFlag(FLAG_STATELESS_HINT, value);
        }
@@ -1030,14 +1028,14 @@
        {
                if (versionManager != null)
                {
-                       return "[Page class = " + getClass().getName() + ", id 
= " + getId() + ", version = "
-                                       + 
versionManager.getCurrentVersionNumber() + ", ajax = "
-                                       + versionManager.getAjaxVersionNumber() 
+ "]";
+                       return "[Page class = " + getClass().getName() + ", id 
= " + getId() + ", version = " +
+                                       
versionManager.getCurrentVersionNumber() + ", ajax = " +
+                                       versionManager.getAjaxVersionNumber() + 
"]";
                }
                else
                {
-                       return "[Page class = " + getClass().getName() + ", id 
= " + getId() + ", version = "
-                                       + 0 + "]";
+                       return "[Page class = " + getClass().getName() + ", id 
= " + getId() + ", version = " +
+                                       0 + "]";
                }
        }
 
@@ -1078,8 +1076,8 @@
                                                        
unrenderedComponents.increment();
 
                                                        // Add to explanatory 
string to buffer
-                                                       
buffer.append(Integer.toString(unrenderedComponents.getCount()) + ". "
-                                                                       + 
component + "\n");
+                                                       
buffer.append(Integer.toString(unrenderedComponents.getCount()) + ". " +
+                                                                       
component + "\n");
                                                        String metadata = 
(String)component
                                                                        
.getMetaData(Component.CONSTRUCTED_AT_KEY);
                                                        if (metadata != null)
@@ -1120,8 +1118,8 @@
 
                                // Throw exception
                                throw new WicketRuntimeException(
-                                               "The component(s) below failed 
to render. A common problem is that you have added a component in code but 
forgot to reference it in the markup (thus the component will never be 
rendered).\n\n"
-                                                               + 
buffer.toString());
+                                               "The component(s) below failed 
to render. A common problem is that you have added a component in code but 
forgot to reference it in the markup (thus the component will never be 
rendered).\n\n" +
+                                                               
buffer.toString());
                        }
                }
 
@@ -1215,8 +1213,8 @@
        {
                // Auto components do not participate in versioning since they 
are
                // added during the rendering phase (which is normally illegal).
-               if (component.isAuto() || (parent == null && 
!component.isVersioned())
-                               || (parent != null && !parent.isVersioned()))
+               if (component.isAuto() || (parent == null && 
!component.isVersioned()) ||
+                               (parent != null && !parent.isVersioned()))
                {
                        return false;
                }
@@ -1330,8 +1328,8 @@
 
                // Write out an xml declaration if the markup stream and 
settings allow
                final MarkupStream markupStream = findMarkupStream();
-               if ((markupStream != null) && (markupStream.getXmlDeclaration() 
!= null)
-                               && 
(application.getMarkupSettings().getStripXmlDeclarationFromOutput() == false))
+               if ((markupStream != null) && (markupStream.getXmlDeclaration() 
!= null) &&
+                               
(application.getMarkupSettings().getStripXmlDeclarationFromOutput() == false))
                {
                        response.write("<?xml version='1.0' encoding='");
                        response.write(encoding);
@@ -1403,7 +1401,7 @@
                dirty();
 
                super.onDetach();
-               
+
        }
 
 

Modified: 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ajax/AjaxRequestTarget.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ajax/AjaxRequestTarget.java?view=diff&rev=559446&r1=559445&r2=559446
==============================================================================
--- 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ajax/AjaxRequestTarget.java
 (original)
+++ 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/ajax/AjaxRequestTarget.java
 Wed Jul 25 06:03:42 2007
@@ -302,8 +302,8 @@
                if (childCriteria == null)
                {
                        throw new IllegalArgumentException(
-                                       "Argument `childCriteria` cannot be 
null. If you want to traverse all components use `"
-                                                       + 
Component.class.getName() + ".class` as the value for this argument");
+                                       "Argument `childCriteria` cannot be 
null. If you want to traverse all components use `" +
+                                                       
Component.class.getName() + ".class` as the value for this argument");
                }
 
 
@@ -334,8 +334,8 @@
                if (component.getOutputMarkupId() == false)
                {
                        throw new IllegalArgumentException(
-                                       "cannot update component that does not 
have setOutputMarkupId property set to true. Component: "
-                                                       + component.toString());
+                                       "cannot update component that does not 
have setOutputMarkupId property set to true. Component: " +
+                                                       component.toString());
                }
                addComponent(component, component.getMarkupId());
        }
@@ -366,9 +366,9 @@
                else if (component instanceof AbstractRepeater)
                {
                        throw new IllegalArgumentException(
-                                       "Component "
-                                                       + 
component.getClass().getName()
-                                                       + " has been added to 
the target. This component is a repeater and cannot be repainted via ajax 
directly. Instead add its parent or another markup container higher in the 
hierarchy.");
+                                       "Component " +
+                                                       
component.getClass().getName() +
+                                                       " has been added to the 
target. This component is a repeater and cannot be repainted via ajax directly. 
Instead add its parent or another markup container higher in the hierarchy.");
                }
 
                markupIdToComponent.put(markupId, component);
@@ -399,8 +399,8 @@
                if (component != null && component.getOutputMarkupId() == false)
                {
                        throw new IllegalArgumentException(
-                                       "cannot update component that does not 
have setOutputMarkupId property set to true. Component: "
-                                                       + component.toString());
+                                       "cannot update component that does not 
have setOutputMarkupId property set to true. Component: " +
+                                                       component.toString());
                }
                final String id = component != null ? component.getMarkupId() : 
null;
                appendJavascript("Wicket.Focus.setFocusOnId('" + id + "');");
@@ -445,9 +445,9 @@
                if (obj instanceof AjaxRequestTarget)
                {
                        AjaxRequestTarget that = (AjaxRequestTarget)obj;
-                       return 
markupIdToComponent.equals(that.markupIdToComponent)
-                                       && 
prependJavascripts.equals(that.prependJavascripts)
-                                       && 
appendJavascripts.equals(that.appendJavascripts);
+                       return 
markupIdToComponent.equals(that.markupIdToComponent) &&
+                                       
prependJavascripts.equals(that.prependJavascripts) &&
+                                       
appendJavascripts.equals(that.appendJavascripts);
                }
                return false;
        }
@@ -668,9 +668,9 @@
         */
        public String toString()
        {
-               return "[AjaxRequestTarget@" + hashCode() + " 
markupIdToComponent [" + markupIdToComponent
-                               + "], prependJavascript [" + prependJavascripts 
+ "], appendJavascript ["
-                               + appendJavascripts + "]";
+               return "[AjaxRequestTarget@" + hashCode() + " 
markupIdToComponent [" + markupIdToComponent +
+                               "], prependJavascript [" + prependJavascripts + 
"], appendJavascript [" +
+                               appendJavascripts + "]";
        }
 
        /**
@@ -732,8 +732,8 @@
                if (component.getRenderBodyOnly() == true)
                {
                        throw new IllegalStateException(
-                                       "Ajax render cannot be called on 
component that has setRenderBodyOnly enabled. Component: "
-                                                       + component.toString());
+                                       "Ajax render cannot be called on 
component that has setRenderBodyOnly enabled. Component: " +
+                                                       component.toString());
                }
 
                component.setOutputMarkupId(true);
@@ -754,11 +754,11 @@
 
                page.startComponentRender(component);
 
-               component.beforeRender();
-               
+               component.prepareForRender();
+
                // render any associated headers of the component
                respondHeaderContribution(response, component);
-               
+
                component.renderComponent();
 
                page.endComponentRender(component);

Modified: 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/list/ListView.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/list/ListView.java?view=diff&rev=559446&r1=559445&r2=559446
==============================================================================
--- 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/list/ListView.java
 (original)
+++ 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/list/ListView.java
 Wed Jul 25 06:03:42 2007
@@ -530,8 +530,6 @@
         */
        protected void onBeforeRender()
        {
-               super.onBeforeRender();
-
                if (isVisibleInHierarchy())
                {
                        // Get number of items to be displayed
@@ -589,7 +587,9 @@
                        {
                                removeAll();
                        }
+
                }
+               super.onBeforeRender();
        }
 
        /**
@@ -665,7 +665,8 @@
                        {
                                final String id = Integer.toString(firstIndex + 
index);
                                index++;
-                               return get(id);
+                               Component c = get(id);
+                               return c;
                        }
                };
        }

Modified: 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/tree/AbstractTree.java
URL: 
http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/tree/AbstractTree.java?view=diff&rev=559446&r1=559445&r2=559446
==============================================================================
--- 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/tree/AbstractTree.java
 (original)
+++ 
incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/tree/AbstractTree.java
 Wed Jul 25 06:03:42 2007
@@ -300,7 +300,7 @@
                
                protected void onBeforeRender()
                {
-                       AbstractTree.this.onBeforeRender();
+                       AbstractTree.this.onBeforeRenderInternal();
                        super.onBeforeRender();
                        
                        if (isRenderChildren())
@@ -559,13 +559,10 @@
        {
        }
 
-       /**
-        * Called at the beginning of the request (not ajax request, unless we 
are
-        * rendering the entire component)
-        */
-       public void onBeforeRender()
+       // This is necessary because MarkupContainer.onBeforeRender involves 
calling
+       // beforeRender on children, which results in stack overflow when 
called from TreeItem
+       private void onBeforeRenderInternal() 
        {
-               super.onBeforeRender();
                if (attached == false)
                {
                        onBeforeAttach();
@@ -606,7 +603,16 @@
 
                        attached = true;
                }
-
+       }
+       
+       /**
+        * Called at the beginning of the request (not ajax request, unless we 
are
+        * rendering the entire component)
+        */
+       public void onBeforeRender()
+       {
+               onBeforeRenderInternal();
+               super.onBeforeRender();
        }
 
        /**


Reply via email to