You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2010/07/11 21:06:14 UTC
svn commit: r963132 - in /tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry5/internal/pageload/
main/java/org/apache/tapestry5/internal/structure/
test/java/org/apache/tapestry5/internal/structure/
Author: hlship
Date: Sun Jul 11 19:06:14 2010
New Revision: 963132
URL: http://svn.apache.org/viewvc?rev=963132&view=rev
Log:
TAP5-1197: Refactor ComponentPageElementImpl to store external state in PerThreadManager
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEvent.java (with props)
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageLoaderImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResources.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSourceImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/PageImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEventHandler.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/PageImplTest.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageLoaderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageLoaderImpl.java?rev=963132&r1=963131&r2=963132&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageLoaderImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageLoaderImpl.java Sun Jul 11 19:06:14 2010
@@ -1,4 +1,4 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2010 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@ import org.apache.tapestry5.ioc.Operatio
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.ioc.internal.util.TapestryException;
+import org.apache.tapestry5.ioc.services.PerthreadManager;
import org.apache.tapestry5.ioc.util.Stack;
import org.apache.tapestry5.model.ComponentModel;
import org.apache.tapestry5.model.EmbeddedComponentModel;
@@ -45,17 +46,17 @@ import java.util.Map;
/**
* There's still a lot of room to beef up {@link org.apache.tapestry5.internal.pageload.ComponentAssembler} and
- * {@link org.apache.tapestry5.internal.pageload.EmbeddedComponentAssembler} to perform more static analysis.
+ * {@link org.apache.tapestry5.internal.pageload.EmbeddedComponentAssembler} to perform more static analysis, but
+ * that may no longer be necessary, given Tapestry 5.2's default use of non-pooled pages.
* <p/>
- * Loading a page involves a recurive process of creating
+ * Loading a page involves a recursive process of creating
* {@link org.apache.tapestry5.internal.pageload.ComponentAssembler}s: for the root component, then down the tree for
* each embedded component. A ComponentAssembler is largely a collection of
* {@link org.apache.tapestry5.internal.pageload.PageAssemblyAction}s. Once created, a ComponentAssembler can quickly
* assemble any number of component instances. All of the expensive logic, such as fitting template tokens together and
* matching parameters to bindings, is done as part of the one-time construction of the ComponentAssembler. The end
* result removes a huge amount of computational redundancy that was present in Tapestry 5.0, but to understand this,
- * you need to split your mind into two phases: construction (of the ComponentAssemblers) and assembly. It's twisted ...
- * and perhaps a bit functional and Monadic.
+ * you need to split your mind into two phases: construction (of the ComponentAssemblers) and assembly.
* <p/>
* And truly, <em>This is the Tapestry Heart, This is the Tapestry Soul...</em>
*/
@@ -135,10 +136,12 @@ public class PageLoaderImpl implements P
private final OperationTracker tracker;
+ private final PerthreadManager perThreadManager;
+
public PageLoaderImpl(ComponentInstantiatorSource instantiatorSource, ComponentTemplateSource templateSource,
PageElementFactory elementFactory, ComponentPageElementResourcesSource resourcesSource,
ComponentClassResolver componentClassResolver, PersistentFieldManager persistentFieldManager,
- StringInterner interner, OperationTracker tracker)
+ StringInterner interner, OperationTracker tracker, PerthreadManager perThreadManager)
{
this.instantiatorSource = instantiatorSource;
this.templateSource = templateSource;
@@ -148,6 +151,7 @@ public class PageLoaderImpl implements P
this.persistentFieldManager = persistentFieldManager;
this.interner = interner;
this.tracker = tracker;
+ this.perThreadManager = perThreadManager;
}
public void objectWasInvalidated()
@@ -163,7 +167,7 @@ public class PageLoaderImpl implements P
{
public Page invoke()
{
- Page page = new PageImpl(logicalPageName, locale, persistentFieldManager);
+ Page page = new PageImpl(logicalPageName, locale, persistentFieldManager, perThreadManager);
ComponentAssembler assembler = getAssembler(pageClassName, locale);
@@ -341,8 +345,8 @@ public class PageLoaderImpl implements P
// Sanity check: since an extension point defines its own default, it's going to be hard to
// not find an override, somewhere, for it.
- throw new TapestryException(PageloadMessages.couldNotFindOverride(extensionPointId), extensionPointToken
- .getLocation(), null);
+ throw new TapestryException(PageloadMessages.couldNotFindOverride(extensionPointId),
+ extensionPointToken.getLocation(), null);
}
private List<ComponentTemplate> buildOverrideSearch(ComponentAssembler assembler, ComponentTemplate template)
@@ -535,8 +539,8 @@ public class PageLoaderImpl implements P
ParameterBinder binder = embeddedAssembler.createParameterBinder(parameterName);
- if (binder == null) { throw new TapestryException(PageloadMessages.parameterNotSupported(element
- .getCompleteId(), parameterName), token.getLocation(), null); }
+ if (binder == null) { throw new TapestryException(PageloadMessages.parameterNotSupported(
+ element.getCompleteId(), parameterName), token.getLocation(), null); }
binder.bind(pageAssembly.createdElement.peek(), binding);
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementImpl.java?rev=963132&r1=963131&r2=963132&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementImpl.java Sun Jul 11 19:06:14 2010
@@ -14,24 +14,13 @@
package org.apache.tapestry5.internal.structure;
-import static org.apache.tapestry5.ioc.internal.util.Defense.notBlank;
-
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
-import org.apache.tapestry5.Binding;
-import org.apache.tapestry5.Block;
-import org.apache.tapestry5.BlockNotFoundException;
-import org.apache.tapestry5.ComponentEventCallback;
-import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.EventContext;
-import org.apache.tapestry5.Link;
-import org.apache.tapestry5.MarkupWriter;
-import org.apache.tapestry5.Renderable;
-import org.apache.tapestry5.TapestryMarkers;
+import org.apache.tapestry5.*;
import org.apache.tapestry5.annotations.AfterRender;
import org.apache.tapestry5.annotations.AfterRenderBody;
import org.apache.tapestry5.annotations.AfterRenderTemplate;
@@ -44,7 +33,6 @@ import org.apache.tapestry5.internal.Abs
import org.apache.tapestry5.internal.InternalComponentResources;
import org.apache.tapestry5.internal.InternalConstants;
import org.apache.tapestry5.internal.services.ComponentEventImpl;
-import org.apache.tapestry5.internal.services.EventImpl;
import org.apache.tapestry5.internal.services.Instantiator;
import org.apache.tapestry5.internal.util.NotificationEventCallback;
import org.apache.tapestry5.ioc.BaseLocatable;
@@ -55,6 +43,7 @@ import org.apache.tapestry5.ioc.internal
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.ioc.internal.util.Orderer;
import org.apache.tapestry5.ioc.internal.util.TapestryException;
+import org.apache.tapestry5.ioc.services.PerThreadValue;
import org.apache.tapestry5.ioc.util.AvailableValues;
import org.apache.tapestry5.ioc.util.UnknownValueException;
import org.apache.tapestry5.model.ComponentModel;
@@ -76,7 +65,10 @@ import org.slf4j.Logger;
* Once instantiated, a ComponentPageElement should be registered as a
* {@linkplain org.apache.tapestry5.internal.structure.Page#addLifecycleListener(org.apache.tapestry5.runtime.PageLifecycleListener)
* lifecycle listener}. This could be done inside the constructors, but that tends to complicate unit tests, so its done
- * by {@link org.apache.tapestry5.internal.services.PageElementFactoryImpl}.
+ * by {@link org.apache.tapestry5.internal.services.PageElementFactoryImpl}. There's still a bit of refactoring in this
+ * class (and its many inner classes) that can improve overall efficiency.
+ * <p>
+ * Modified for Tapestry 5.2 to adjust for the no-pooling approach (shared instances with externalized mutable state).
*/
public class ComponentPageElementImpl extends BaseLocatable implements ComponentPageElement, PageLifecycleListener
{
@@ -153,17 +145,21 @@ public class ComponentPageElementImpl ex
return list == null ? 0 : list.size();
}
- private abstract class AbstractPhase extends AbstractComponentCallback implements RenderCommand
+ private abstract class AbstractPhase implements RenderCommand
{
private final String name;
- private MarkupWriter writer;
+ private final boolean reverse;
- public AbstractPhase(String name)
+ AbstractPhase(String name)
{
- super(sharedEvent);
+ this(name, false);
+ }
+ AbstractPhase(String name, boolean reverse)
+ {
this.name = name;
+ this.reverse = reverse;
}
@Override
@@ -172,34 +168,39 @@ public class ComponentPageElementImpl ex
return phaseToString(name);
}
- void reset(RenderQueue queue)
+ void invoke(MarkupWriter writer, Event event)
{
- sharedEventHandler.queueCommands(queue);
-
- sharedEventHandler.reset();
+ try
+ {
+ if (components == null)
+ {
+ invokeComponent(coreComponent, writer, event);
+ return;
+ }
- sharedEvent.reset();
+ // Multiple components (i.e., some mixins).
- writer = null;
- }
+ Iterator<Component> i = reverse ? InternalUtils.reverseIterator(components) : components.iterator();
- void callback(boolean reverse, MarkupWriter writer)
- {
- this.writer = writer;
+ while (i.hasNext())
+ {
+ invokeComponent(i.next(), writer, event);
- invoke(reverse, this);
- }
-
- public void run(Component component)
- {
- invokeComponent(component, writer, sharedEvent);
- }
+ if (event.isAborted())
+ break;
+ }
+ }
+ catch (RuntimeException ex)
+ {
+ throw new TapestryException(ex.getMessage(), getLocation(), ex);
+ }
- protected boolean getResult()
- {
- return sharedEventHandler.getResult();
}
+ /**
+ * Each concrete class implements this method to branch to the corresponding method
+ * of {@link Component}.
+ */
protected abstract void invokeComponent(Component component, MarkupWriter writer, Event event);
}
@@ -215,13 +216,15 @@ public class ComponentPageElementImpl ex
component.setupRender(writer, event);
}
- public void render(final MarkupWriter writer, RenderQueue queue)
+ public void render(MarkupWriter writer, RenderQueue queue)
{
- callback(false, writer);
+ RenderPhaseEvent event = createRenderEvent(queue);
+
+ invoke(writer, event);
- push(queue, getResult(), beginRenderPhase, cleanupRenderPhase);
+ push(queue, event.getResult(), beginRenderPhase, cleanupRenderPhase);
- reset(queue);
+ event.reset();
}
}
@@ -239,12 +242,14 @@ public class ComponentPageElementImpl ex
public void render(final MarkupWriter writer, final RenderQueue queue)
{
- callback(false, writer);
+ RenderPhaseEvent event = createRenderEvent(queue);
+
+ invoke(writer, event);
push(queue, afterRenderPhase);
- push(queue, getResult(), beforeRenderTemplatePhase, null);
+ push(queue, event.getResult(), beforeRenderTemplatePhase, null);
- reset(queue);
+ event.reset();
}
}
@@ -287,14 +292,16 @@ public class ComponentPageElementImpl ex
public void render(final MarkupWriter writer, final RenderQueue queue)
{
- callback(false, writer);
+ RenderPhaseEvent event = createRenderEvent(queue);
+
+ invoke(writer, event);
push(queue, afterRenderTemplatePhase);
- if (getResult())
+ if (event.getResult())
pushElements(queue, template);
- reset(queue);
+ event.reset();
}
}
@@ -332,14 +339,16 @@ public class ComponentPageElementImpl ex
public void render(final MarkupWriter writer, RenderQueue queue)
{
- callback(false, writer);
+ RenderPhaseEvent event = createRenderEvent(queue);
+
+ invoke(writer, event);
push(queue, afterRenderBodyPhase);
- if (getResult() && bodyBlock != null)
+ if (event.getResult() && bodyBlock != null)
queue.push(bodyBlock);
- reset(queue);
+ event.reset();
}
}
@@ -348,7 +357,7 @@ public class ComponentPageElementImpl ex
private AfterRenderBodyPhase()
{
- super("AfterRenderBody");
+ super("AfterRenderBody", true);
}
protected void invokeComponent(Component component, MarkupWriter writer, Event event)
@@ -358,11 +367,13 @@ public class ComponentPageElementImpl ex
public void render(final MarkupWriter writer, RenderQueue queue)
{
- callback(true, writer);
+ RenderPhaseEvent event = createRenderEvent(queue);
+
+ invoke(writer, event);
- push(queue, getResult(), null, beforeRenderBodyPhase);
+ push(queue, event.getResult(), null, beforeRenderBodyPhase);
- reset(queue);
+ event.reset();
}
}
@@ -370,7 +381,7 @@ public class ComponentPageElementImpl ex
{
private AfterRenderTemplatePhase()
{
- super("AfterRenderTemplate");
+ super("AfterRenderTemplate", true);
}
protected void invokeComponent(Component component, MarkupWriter writer, Event event)
@@ -380,11 +391,13 @@ public class ComponentPageElementImpl ex
public void render(final MarkupWriter writer, final RenderQueue queue)
{
- callback(true, writer);
+ RenderPhaseEvent event = createRenderEvent(queue);
- push(queue, getResult(), null, beforeRenderTemplatePhase);
+ invoke(writer, event);
- reset(queue);
+ push(queue, event.getResult(), null, beforeRenderTemplatePhase);
+
+ event.reset();
}
}
@@ -392,7 +405,7 @@ public class ComponentPageElementImpl ex
{
private AfterRenderPhase()
{
- super("AfterRender");
+ super("AfterRender", true);
}
protected void invokeComponent(Component component, MarkupWriter writer, Event event)
@@ -402,21 +415,21 @@ public class ComponentPageElementImpl ex
public void render(final MarkupWriter writer, RenderQueue queue)
{
- callback(true, writer);
+ RenderPhaseEvent event = createRenderEvent(queue);
+
+ invoke(writer, event);
- push(queue, getResult(), cleanupRenderPhase, beginRenderPhase);
+ push(queue, event.getResult(), cleanupRenderPhase, beginRenderPhase);
- reset(queue);
+ event.reset();
}
}
- private final ComponentPageElementResources elementResources;
-
private class CleanupRenderPhase extends AbstractPhase
{
private CleanupRenderPhase()
{
- super("CleanupRender");
+ super("CleanupRender", true);
}
protected void invokeComponent(Component component, MarkupWriter writer, Event event)
@@ -426,11 +439,13 @@ public class ComponentPageElementImpl ex
public void render(final MarkupWriter writer, RenderQueue queue)
{
- callback(true, writer);
+ RenderPhaseEvent event = createRenderEvent(queue);
- push(queue, getResult(), null, setupRenderPhase);
+ invoke(writer, event);
- reset(queue);
+ push(queue, event.getResult(), null, setupRenderPhase);
+
+ event.reset();
}
}
@@ -453,7 +468,7 @@ public class ComponentPageElementImpl ex
public void render(MarkupWriter writer, RenderQueue queue)
{
- rendering = false;
+ rendering.set(false);
Element current = writer.getElement();
@@ -496,12 +511,13 @@ public class ComponentPageElementImpl ex
/**
* Component lifecycle instances for all mixins; the core component is added to this list during
- * page load. This is
- * only used in the case that a component has mixins (in which case, the core component is
+ * page load. This is only used in the case that a component has mixins (in which case, the core component is
* listed last).
*/
private List<Component> components = null;
+ private final ComponentPageElementResources elementResources;
+
private final ComponentPageElement container;
private final InternalComponentResources coreResources;
@@ -525,22 +541,18 @@ public class ComponentPageElementImpl ex
private final Page page;
- private boolean rendering;
+ private final PerThreadValue<RenderPhaseEvent> renderEvent;
+
+ private final PerThreadValue<Boolean> rendering;
// We know that, at the very least, there will be an element to force the component to render
// its body, so there's no reason to wait to initialize the list.
private final List<RenderCommand> template = CollectionFactory.newList();
- private boolean renderPhasesInitalized;
-
private RenderCommand setupRenderPhase, beginRenderPhase, beforeRenderTemplatePhase, beforeRenderBodyPhase,
afterRenderBodyPhase, afterRenderTemplatePhase, afterRenderPhase, cleanupRenderPhase;
- private final RenderPhaseEventHandler sharedEventHandler = new RenderPhaseEventHandler();
-
- private final EventImpl sharedEvent;
-
/**
* Constructor for other components embedded within the root component or at deeper levels of
* the hierarchy.
@@ -563,7 +575,6 @@ public class ComponentPageElementImpl ex
* @param elementResources
* Provides access to common methods of various services
*/
-
ComponentPageElementImpl(Page page, ComponentPageElement container, String id, String nestedId, String completeId,
String elementName, Instantiator instantiator, Location location,
ComponentPageElementResources elementResources)
@@ -585,10 +596,10 @@ public class ComponentPageElementImpl ex
coreComponent = coreResources.getComponent();
- Logger logger = coreResources.getLogger();
- eventLogger = elementResources.getEventLogger(logger);
+ eventLogger = elementResources.getEventLogger(coreResources.getLogger());
- sharedEvent = new EventImpl(sharedEventHandler, eventLogger);
+ renderEvent = elementResources.createPerThreadValue("tapestry.internal.RenderEvent:" + completeId);
+ rendering = elementResources.createPerThreadValue("tapestry.internal.Rendering:" + completeId);
}
/**
@@ -601,9 +612,6 @@ public class ComponentPageElementImpl ex
private void initializeRenderPhases()
{
- if (renderPhasesInitalized)
- return;
-
setupRenderPhase = new SetupRenderPhase();
beginRenderPhase = new BeginRenderPhase();
beforeRenderTemplatePhase = new BeforeRenderTemplatePhase();
@@ -652,8 +660,6 @@ public class ComponentPageElementImpl ex
if (!handled.contains(SetupRender.class))
setupRenderPhase = beginRenderPhase;
-
- renderPhasesInitalized = true;
}
public ComponentPageElement newChild(String id, String nestedId, String completeId, String elementName,
@@ -689,8 +695,8 @@ public class ComponentPageElementImpl ex
if (existing != null)
throw new TapestryException(StructureMessages.duplicateChildComponent(this, childId), child,
- new TapestryException(StructureMessages.originalChildComponent(this, childId, existing
- .getLocation()), existing, null));
+ new TapestryException(StructureMessages.originalChildComponent(this, childId,
+ existing.getLocation()), existing, null));
children.put(childId, child);
}
@@ -818,24 +824,22 @@ public class ComponentPageElementImpl ex
mixinAfterOrderer = null;
}
- loaded = true;
-
// For some parameters, bindings (from defaults) are provided inside the callback method, so
// that is invoked first, before we check for unbound parameters.
invoke(false, CONTAINING_PAGE_DID_LOAD);
verifyRequiredParametersAreBound();
- }
- public void enqueueBeforeRenderBody(RenderQueue queue)
- {
- // TAP5-1100: In certain Ajax cases, a component may be asked to render its body
- // that has never rendered itself (and thus, never called initializeRenderPhases). Subtle.
+ // We assume that by the time we start to render, the structure (i.e., mixins) is nailed
+ // down. We could add a lock, but that seems wasteful.
initializeRenderPhases();
- // If no body, then no beforeRenderBody or afterRenderBody
+ loaded = true;
+ }
+ public void enqueueBeforeRenderBody(RenderQueue queue)
+ {
if (bodyBlock != null)
push(queue, beforeRenderBodyPhase);
}
@@ -967,7 +971,7 @@ public class ComponentPageElementImpl ex
{
try
{ // Optimization: In the most general case (just the one component, no mixins)
- // invoke the callback on the component and be done ... no iterators, no nothing.
+ // invoke the callback on the component and be done ... no iterators, no nothing.
if (components == null)
{
@@ -998,7 +1002,7 @@ public class ComponentPageElementImpl ex
public boolean isRendering()
{
- return rendering;
+ return rendering.exists() && rendering.get();
}
/**
@@ -1014,11 +1018,6 @@ public class ComponentPageElementImpl ex
*/
public final void render(MarkupWriter writer, RenderQueue queue)
{
- // We assume that by the time we start to render, the structure (i.e., mixins) is nailed
- // down. We could add a lock, but that seems wasteful.
-
- initializeRenderPhases();
-
// TODO: An error if the render flag is already set (recursive rendering not
// allowed or advisable).
@@ -1028,7 +1027,7 @@ public class ComponentPageElementImpl ex
// TODO: Check for recursive rendering.
- rendering = true;
+ rendering.set(true);
queue.startComponent(coreResources);
@@ -1082,6 +1081,7 @@ public class ComponentPageElementImpl ex
});
}
+ @SuppressWarnings("all")
private boolean processEventTriggering(String eventType, EventContext context, ComponentEventCallback callback)
{
boolean result = false;
@@ -1219,7 +1219,7 @@ public class ComponentPageElementImpl ex
public Block findBlock(String id)
{
- notBlank(id, "id");
+ Defense.notBlank(id, "id");
return InternalUtils.get(blocks, id);
}
@@ -1285,4 +1285,21 @@ public class ComponentPageElementImpl ex
return elementResources.createPageRenderLink(pageClass, override, context);
}
+ protected RenderPhaseEvent createRenderEvent(RenderQueue queue)
+ {
+ RenderPhaseEvent result = renderEvent.get();
+
+ if (result != null)
+ return result;
+
+ // Create a per-thread value to use until the end of the render.
+ // This assumes that the queue will not change during the current request,
+ // which should be valid.
+
+ result = new RenderPhaseEvent(new RenderPhaseEventHandler(queue), eventLogger);
+
+ renderEvent.set(result);
+
+ return result;
+ }
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResources.java?rev=963132&r1=963131&r2=963132&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResources.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResources.java Sun Jul 11 19:06:14 2010
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,8 @@ import org.apache.tapestry5.ComponentRes
import org.apache.tapestry5.Link;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.OperationTracker;
+import org.apache.tapestry5.ioc.services.PerThreadValue;
+import org.apache.tapestry5.ioc.services.PerthreadManager;
import org.apache.tapestry5.model.ComponentModel;
import org.apache.tapestry5.services.ContextValueEncoder;
import org.slf4j.Logger;
@@ -32,7 +34,7 @@ public interface ComponentPageElementRes
* Used to obtain a {@link org.apache.tapestry5.ioc.Messages} instance for a particular component. If the component
* extends from another component, then its localized properties will merge with its parent's properties (with the
* subclass overriding the super class on any conflicts).
- *
+ *
* @param componentModel
* @return the message catalog for the component, in the indicated locale
* @see org.apache.tapestry5.services.messages.ComponentMessagesSource
@@ -44,11 +46,14 @@ public interface ComponentPageElementRes
* conversion will be to the equivalent wrapper type. In some cases, the TypeCoercer will need to search for an
* appropriate coercion, and may even combine existing coercions to form new ones; in those cases, the results of
* the search are cached.
- *
- * @param <S> source type (input)
- * @param <T> target type (output)
+ *
+ * @param <S>
+ * source type (input)
+ * @param <T>
+ * target type (output)
* @param input
- * @param targetType defines the target type
+ * @param targetType
+ * defines the target type
* @return the coerced value
* @see org.apache.tapestry5.ioc.services.TypeCoercer
*/
@@ -56,8 +61,9 @@ public interface ComponentPageElementRes
/**
* Gets the Class instance for then give name.
- *
- * @param className fully qualified class name
+ *
+ * @param className
+ * fully qualified class name
* @return the class instance
* @see org.apache.tapestry5.internal.services.ComponentClassCache
*/
@@ -65,11 +71,15 @@ public interface ComponentPageElementRes
/**
* Creates a link on behalf of a component.
- *
- * @param resources resources for the component
- * @param eventType type of event to create
- * @param forForm true if generating for a form submission
- * @param context additional event context associated with the link
+ *
+ * @param resources
+ * resources for the component
+ * @param eventType
+ * type of event to create
+ * @param forForm
+ * true if generating for a form submission
+ * @param context
+ * additional event context associated with the link
* @return the link
* @since 5.1.0.0
*/
@@ -77,12 +87,15 @@ public interface ComponentPageElementRes
/**
* Creates a page render request link to render a specific page.
- *
- * @param pageName the logical name of the page to link to
- * @param override if true, the context is used even if empty (normally, the target page is allowed to passivate,
- * providing a context, when the provided context is empty)
- * @param context the activation context for the page. If omitted, the activation context is obtained from the
- * target page
+ *
+ * @param pageName
+ * the logical name of the page to link to
+ * @param override
+ * if true, the context is used even if empty (normally, the target page is allowed to passivate,
+ * providing a context, when the provided context is empty)
+ * @param context
+ * the activation context for the page. If omitted, the activation context is obtained from the
+ * target page
* @return link for a render request to the targetted page
* @since 5.1.0.0
*/
@@ -91,23 +104,34 @@ public interface ComponentPageElementRes
/**
* Creates a page render request link to render a specific page. Using a page class, rather than a page name, is
* more refactoring safe (in the even the page is renamed or moved).
- *
- * @param pageClass identifies the page to link to
- * @param override if true, the context is used even if empty (normally, the target page is allowed to passivate,
- * providing a context, when the provided context is empty)
- * @param context the activation context for the page. If omitted, the activation context is obtained from the
- * target page
+ *
+ * @param pageClass
+ * identifies the page to link to
+ * @param override
+ * if true, the context is used even if empty (normally, the target page is allowed to passivate,
+ * providing a context, when the provided context is empty)
+ * @param context
+ * the activation context for the page. If omitted, the activation context is obtained from the
+ * target page
* @return link for a render request to the targetted page
* @since 5.1
*/
Link createPageRenderLink(Class pageClass, boolean override, Object... context);
/**
- * Returns the event logger for the provided component logger. The event logger is based on the component logger's
+ * Returns the event logger for the provided component logger. The event logger is based on the component logger's
* name (which matches the component class name) with a "tapestry..events." prefix.
- *
- * @param componentLogger provides base name for logger
+ *
+ * @param componentLogger
+ * provides base name for logger
* @return the logger
*/
Logger getEventLogger(Logger componentLogger);
+
+ /**
+ * Wrapper around {@link PerthreadManager#createValue(Object)}.
+ *
+ * @since 5.2.0
+ */
+ <T> PerThreadValue<T> createPerThreadValue(Object key);
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesImpl.java?rev=963132&r1=963131&r2=963132&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesImpl.java Sun Jul 11 19:06:14 2010
@@ -16,6 +16,7 @@ package org.apache.tapestry5.internal.st
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Link;
+import org.apache.tapestry5.internal.InternalConstants;
import org.apache.tapestry5.internal.services.ComponentClassCache;
import org.apache.tapestry5.internal.services.LinkSource;
import org.apache.tapestry5.internal.services.RequestPageCache;
@@ -24,6 +25,8 @@ import org.apache.tapestry5.ioc.LoggerSo
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.OperationTracker;
import org.apache.tapestry5.ioc.internal.util.Defense;
+import org.apache.tapestry5.ioc.services.PerThreadValue;
+import org.apache.tapestry5.ioc.services.PerthreadManager;
import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.model.ComponentModel;
import org.apache.tapestry5.services.ComponentClassResolver;
@@ -35,8 +38,6 @@ import java.util.Locale;
public class ComponentPageElementResourcesImpl implements ComponentPageElementResources
{
- private static final Object[] EMPTY = new Object[0];
-
private final Locale locale;
private final ComponentMessagesSource componentMessagesSource;
@@ -57,10 +58,12 @@ public class ComponentPageElementResourc
private final OperationTracker tracker;
+ private final PerthreadManager perThreadManager;
+
public ComponentPageElementResourcesImpl(Locale locale, ComponentMessagesSource componentMessagesSource,
TypeCoercer typeCoercer, ComponentClassCache componentClassCache, ContextValueEncoder contextValueEncoder,
LinkSource linkSource, RequestPageCache requestPageCache, ComponentClassResolver componentClassResolver,
- LoggerSource loggerSource, OperationTracker tracker)
+ LoggerSource loggerSource, OperationTracker tracker, PerthreadManager perThreadManager)
{
this.componentMessagesSource = componentMessagesSource;
this.locale = locale;
@@ -72,6 +75,7 @@ public class ComponentPageElementResourc
this.componentClassResolver = componentClassResolver;
this.loggerSource = loggerSource;
this.tracker = tracker;
+ this.perThreadManager = perThreadManager;
}
public Messages getMessages(ComponentModel componentModel)
@@ -131,7 +135,7 @@ public class ComponentPageElementResourc
private Object[] defaulted(Object[] context)
{
- return context == null ? EMPTY : context;
+ return context == null ? InternalConstants.EMPTY_STRING_ARRAY: context;
}
public <T> T invoke(String description, Invokable<T> operation)
@@ -143,4 +147,10 @@ public class ComponentPageElementResourc
{
tracker.run(description, operation);
}
+
+ public <T> PerThreadValue<T> createPerThreadValue(Object key)
+ {
+ return perThreadManager.createValue(key);
+ }
+
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSourceImpl.java?rev=963132&r1=963131&r2=963132&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementResourcesSourceImpl.java Sun Jul 11 19:06:14 2010
@@ -21,6 +21,7 @@ import org.apache.tapestry5.ioc.LoggerSo
import org.apache.tapestry5.ioc.OperationTracker;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.Defense;
+import org.apache.tapestry5.ioc.services.PerthreadManager;
import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.services.ComponentClassResolver;
import org.apache.tapestry5.services.ContextValueEncoder;
@@ -51,10 +52,12 @@ public class ComponentPageElementResourc
private final OperationTracker tracker;
+ private final PerthreadManager perThreadManager;
+
public ComponentPageElementResourcesSourceImpl(ComponentMessagesSource componentMessagesSource,
TypeCoercer typeCoercer, ComponentClassCache componentClassCache, ContextValueEncoder contextValueEncoder,
LinkSource linkSource, RequestPageCache requestPageCache, ComponentClassResolver componentClassResolver,
- LoggerSource loggerSource, OperationTracker tracker)
+ LoggerSource loggerSource, OperationTracker tracker, PerthreadManager perThreadManager)
{
this.componentMessagesSource = componentMessagesSource;
this.typeCoercer = typeCoercer;
@@ -65,6 +68,7 @@ public class ComponentPageElementResourc
this.componentClassResolver = componentClassResolver;
this.loggerSource = loggerSource;
this.tracker = tracker;
+ this.perThreadManager = perThreadManager;
}
public ComponentPageElementResources get(Locale locale)
@@ -77,7 +81,7 @@ public class ComponentPageElementResourc
{
result = new ComponentPageElementResourcesImpl(locale, componentMessagesSource, typeCoercer,
componentClassCache, contextValueEncoder, linkSource, requestPageCache, componentClassResolver,
- loggerSource, tracker);
+ loggerSource, tracker, perThreadManager);
// Small race condition here, where we may create two instances of the CPER for the same locale,
// but that's not worth worrying about.
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java?rev=963132&r1=963131&r2=963132&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java Sun Jul 11 19:06:14 2010
@@ -15,6 +15,7 @@
package org.apache.tapestry5.internal.structure;
import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.ioc.services.PerthreadManager;
import org.apache.tapestry5.runtime.Component;
import org.apache.tapestry5.runtime.PageLifecycleListener;
import org.slf4j.Logger;
@@ -26,8 +27,14 @@ import java.util.Locale;
* application; end developers who refer to "page" are really referring to the {@link #getRootComponent() root
* component} of the actual page.
* <p/>
- * One of the most important aspects of a Page is that it <em>does not</em> have to be coded in a thread-safe manner.
- * Pages are always accessed within a single thread, associated with a single incoming request.
+ * Starting in release 5.2, the nature of pages changed considerably. Pages are no longer pooled instances. Instead,
+ * pages are shared instances (per locale) but all internal <em>mutable</em> state is stored inside
+ * {@link PerthreadManager}. Page construction time is considered to extend past the
+ * {@link PageLifecycleListener#containingPageDidLoad()} lifecycle notification. This is not quite perfect from a
+ * threading point-of-view (arguably, even write-once-read-many fields should be protected by synchronized blocks or
+ * other mechanisms). At best, we can be assured that the entire page construction phase is protected by a single
+ * synchronized block (but not on the page itself). An ideal system would build the page bottom to top so that all
+ * assignments could take place in constructors, assigning to final fields. Maybe some day.
* <p/>
* The Page object is never visible to end-user code. The page also exists to provide a kind of service to components
* embedded (directly or indirectly) within the page.
@@ -71,9 +78,13 @@ public interface Page
* <p/>
* A page may be clean or dirty. A page is dirty if its dirty count is greater than zero (meaning that, during the
* render of the page, some components did not fully render), or if any of its listeners throw an exception from
- * containingPageDidDetech().
+ * containingPageDidDetach().
* <p/>
* The page pool should discard pages that are dirty, rather than store them into the pool.
+ * <p>
+ * Under Tapestry 5.2 and pool-less pages, the result is ignored; all mutable state is expected to be discarded
+ * automatically from the {@link PerthreadManager}. A future release of Tapestry will likely convert this method to
+ * type void.
*
* @return true if the page is "dirty", false otherwise
* @see org.apache.tapestry5.runtime.PageLifecycleListener#containingPageDidDetach()
@@ -82,11 +93,12 @@ public interface Page
/**
* Invoked to inform the page that it is attached to the current request. This occurs when a
- * page is first
- * referenced within a request. If the page was created from scratch for this request, the call
+ * page is first referenced within a request. If the page was created from scratch for this request, the call
* to {@link #loaded()} will preceded the call to {@link #attached()}.
+ * <p>
+ * First all listeners have {@link PageLifecycleListener#restoreStateBeforePageAttach()} invoked, followed by
+ * {@link PageLifecycleListener#containingPageDidAttach()}.
*/
-
void attached();
/**
@@ -94,7 +106,6 @@ public interface Page
*
* @see org.apache.tapestry5.runtime.PageLifecycleListener#containingPageDidLoad()
*/
-
void loaded();
/**
@@ -157,11 +168,15 @@ public interface Page
* where a component
* causes a runtime exception that aborts the render early, leaving the page in an invalid
* state.
+ *
+ * @deprecated No longer useful with non-pooled pages, to be removed for efficiency
*/
void incrementDirtyCount();
/**
* Called as a component finishes rendering itself.
+ *
+ * @deprecated No longer useful with non-pooled pages, to be removed for efficiency
*/
void decrementDirtyCount();
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/PageImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/PageImpl.java?rev=963132&r1=963131&r2=963132&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/PageImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/PageImpl.java Sun Jul 11 19:06:14 2010
@@ -18,9 +18,12 @@ import org.apache.tapestry5.ComponentRes
import org.apache.tapestry5.internal.services.PersistentFieldManager;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.Defense;
+import org.apache.tapestry5.ioc.internal.util.OneShotLock;
import static org.apache.tapestry5.ioc.internal.util.Defense.notNull;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.services.PerThreadValue;
+import org.apache.tapestry5.ioc.services.PerthreadManager;
import org.apache.tapestry5.runtime.Component;
import org.apache.tapestry5.runtime.PageLifecycleListener;
import org.apache.tapestry5.services.PersistentFieldBundle;
@@ -43,10 +46,12 @@ public class PageImpl implements Page
private final List<PageResetListener> resetListeners = CollectionFactory.newList();
- private int dirtyCount;
+ private final PerThreadValue<Integer> dirtyCount;
private boolean loadComplete;
+ private final OneShotLock lock = new OneShotLock();
+
/**
* Obtained from the {@link org.apache.tapestry5.internal.services.PersistentFieldManager} when
* first needed,
@@ -54,11 +59,14 @@ public class PageImpl implements Page
*/
private PersistentFieldBundle fieldBundle;
- public PageImpl(String name, Locale locale, PersistentFieldManager persistentFieldManager)
+ public PageImpl(String name, Locale locale, PersistentFieldManager persistentFieldManager,
+ PerthreadManager perThreadManager)
{
this.name = name;
this.locale = locale;
this.persistentFieldManager = persistentFieldManager;
+
+ dirtyCount = perThreadManager.createValue("PageDirtyCount:" + name);
}
@Override
@@ -93,6 +101,8 @@ public class PageImpl implements Page
public void setRootElement(ComponentPageElement component)
{
+ lock.check();
+
rootElement = component;
}
@@ -108,17 +118,21 @@ public class PageImpl implements Page
public void addLifecycleListener(PageLifecycleListener listener)
{
+ lock.check();
+
lifecycleListeners.add(listener);
}
public void removeLifecycleListener(PageLifecycleListener listener)
{
+ lock.check();
+
lifecycleListeners.remove(listener);
}
public boolean detached()
{
- boolean result = dirtyCount > 0;
+ boolean result = dirtyCount.exists() ? dirtyCount.get() > 0 : false;
for (PageLifecycleListener listener : lifecycleListeners)
{
@@ -140,15 +154,19 @@ public class PageImpl implements Page
public void loaded()
{
+ lock.check();
+
for (PageLifecycleListener listener : lifecycleListeners)
listener.containingPageDidLoad();
loadComplete = true;
+
+ lock.lock();
}
public void attached()
{
- if (dirtyCount != 0)
+ if (dirtyCount.exists() && !dirtyCount.get().equals(0))
throw new IllegalStateException(StructureMessages.pageIsDirty(this));
for (PageLifecycleListener listener : lifecycleListeners)
@@ -181,7 +199,9 @@ public class PageImpl implements Page
public void decrementDirtyCount()
{
- dirtyCount--;
+ int newCount = dirtyCount.get() - 1;
+
+ dirtyCount.set(newCount);
}
public void discardPersistentFieldChanges()
@@ -191,7 +211,9 @@ public class PageImpl implements Page
public void incrementDirtyCount()
{
- dirtyCount++;
+ int newCount = dirtyCount.exists() ? dirtyCount.get() + 1 : 1;
+
+ dirtyCount.set(newCount);
}
public String getName()
@@ -202,6 +224,8 @@ public class PageImpl implements Page
public void addResetListener(PageResetListener listener)
{
Defense.notNull(listener, "listener");
+
+ lock.check();
resetListeners.add(listener);
}
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEvent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEvent.java?rev=963132&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEvent.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEvent.java Sun Jul 11 19:06:14 2010
@@ -0,0 +1,43 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.structure;
+
+import org.apache.tapestry5.internal.services.EventImpl;
+import org.slf4j.Logger;
+
+public class RenderPhaseEvent extends EventImpl
+{
+ private final RenderPhaseEventHandler handler;
+
+ public RenderPhaseEvent(RenderPhaseEventHandler handler, Logger logger)
+ {
+ super(handler, logger);
+
+ this.handler = handler;
+
+ }
+
+ public void reset()
+ {
+ super.reset();
+
+ handler.reset();
+ }
+
+ public boolean getResult()
+ {
+ return handler.getResult();
+ }
+}
Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEvent.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEventHandler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEventHandler.java?rev=963132&r1=963131&r2=963132&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEventHandler.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEventHandler.java Sun Jul 11 19:06:14 2010
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,15 +27,22 @@ import org.apache.tapestry5.runtime.Rend
/**
* Used by {@link org.apache.tapestry5.internal.structure.ComponentPageElementImpl} to track the results of invoking the
* component methods for a render phase event.
- *
+ *
* @since 5.0.19
*/
class RenderPhaseEventHandler implements ComponentEventCallback
{
+ private final RenderQueue renderQueue;
+
private boolean result = true;
private List<RenderCommand> commands;
+ public RenderPhaseEventHandler(RenderQueue renderQueue)
+ {
+ this.renderQueue = renderQueue;
+ }
+
boolean getResult()
{
return result;
@@ -43,6 +50,12 @@ class RenderPhaseEventHandler implements
void reset()
{
+ if (commands != null)
+ {
+ for (RenderCommand command : commands)
+ renderQueue.push(command);
+ }
+
result = true;
commands = null;
@@ -82,22 +95,16 @@ class RenderPhaseEventHandler implements
return false;
}
- throw new RuntimeException(StructureMessages.wrongPhaseResultType(
- Arrays.asList(Boolean.class.getName(), Renderable.class.getName(), RenderCommand.class.getName())));
+ throw new RuntimeException(StructureMessages.wrongPhaseResultType(Arrays.asList(Boolean.class.getName(),
+ Renderable.class.getName(), RenderCommand.class.getName())));
}
private void add(RenderCommand command)
{
- if (commands == null) commands = CollectionFactory.newList();
+ if (commands == null)
+ commands = CollectionFactory.newList();
commands.add(command);
}
- public void queueCommands(RenderQueue queue)
- {
- if (commands == null) return;
-
- for (RenderCommand command : commands)
- queue.push(command);
- }
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/PageImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/PageImplTest.java?rev=963132&r1=963131&r2=963132&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/PageImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/PageImplTest.java Sun Jul 11 19:06:14 2010
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,10 +15,13 @@
package org.apache.tapestry5.internal.structure;
import org.apache.tapestry5.internal.test.InternalBaseTestCase;
+import org.apache.tapestry5.ioc.services.PerthreadManager;
import org.apache.tapestry5.runtime.PageLifecycleListener;
import static org.easymock.EasyMock.contains;
import static org.easymock.EasyMock.same;
import org.slf4j.Logger;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.Locale;
@@ -29,6 +32,20 @@ public class PageImplTest extends Intern
private static final String LOGICAL_PAGE_NAME = "MyPage";
+ private PerthreadManager perThreadManager;
+
+ @BeforeClass
+ public void setup()
+ {
+ perThreadManager = getService(PerthreadManager.class);
+ }
+
+ @AfterMethod
+ public void cleanup()
+ {
+ perThreadManager.cleanup();
+ }
+
@Test
public void accessor_methods()
{
@@ -36,7 +53,7 @@ public class PageImplTest extends Intern
replay();
- Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null);
+ Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null, perThreadManager);
assertNull(page.getRootElement());
@@ -60,7 +77,7 @@ public class PageImplTest extends Intern
replay();
- Page page = new PageImpl(null, locale, null);
+ Page page = new PageImpl(null, locale, null, perThreadManager);
page.addLifecycleListener(listener1);
page.addLifecycleListener(listener2);
@@ -82,7 +99,7 @@ public class PageImplTest extends Intern
replay();
- Page page = new PageImpl(null, locale, null);
+ Page page = new PageImpl(null, locale, null, perThreadManager);
page.addLifecycleListener(listener);
@@ -116,7 +133,7 @@ public class PageImplTest extends Intern
replay();
- Page page = new PageImpl(null, locale, null);
+ Page page = new PageImpl(null, locale, null, perThreadManager);
page.setRootElement(element);
page.addLifecycleListener(listener1);
@@ -146,7 +163,7 @@ public class PageImplTest extends Intern
replay();
- Page page = new PageImpl(null, locale, null);
+ Page page = new PageImpl(null, locale, null, perThreadManager);
page.addLifecycleListener(listener1);
page.addLifecycleListener(listener2);
@@ -172,7 +189,7 @@ public class PageImplTest extends Intern
replay();
- Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null);
+ Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null, perThreadManager);
page.addLifecycleListener(listener1);
page.addLifecycleListener(listener2);
@@ -189,7 +206,7 @@ public class PageImplTest extends Intern
replay();
- Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null);
+ Page page = new PageImpl(LOGICAL_PAGE_NAME, locale, null, perThreadManager);
page.setRootElement(root);