This is an automated email from the ASF dual-hosted git repository. thiagohp pushed a commit to branch TAP5-2779 in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
commit 3e675d6bbf967b4b8ce50e773fc54163b5b40360 Author: Thiago H. de Paula Figueiredo <[email protected]> AuthorDate: Tue Jul 9 23:34:11 2024 -0300 TAP5-2779: avoiding an infinite method call recursion bug --- .../internal/services/ComponentModelSourceImpl.java | 9 ++++++--- .../tapestry5/internal/services/PageSourceImpl.java | 17 +++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSourceImpl.java index 918d05e87..dcbfbc47e 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSourceImpl.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSourceImpl.java @@ -65,10 +65,13 @@ public class ComponentModelSourceImpl implements ComponentModelSource { pageSource.getPage(resolver.getLogicalName(componentClassName)); } - catch (Exception e) + catch (IllegalStateException e) { - e.printStackTrace(); - //ignore + // This can be thrown in PageSourceImpl in case an + // infinite method call recursion is detected. In + // that case, the page instance is already created, + // so the objective of the line above is already + // fulfilled and we can safely ignore the exception } } } diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java index bc29a45af..38ab835fd 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java @@ -110,6 +110,9 @@ public class PageSourceImpl implements PageSource private final Map<CachedPageKey, Object> pageCache = CollectionFactory.newConcurrentMap(); private final Map<String, Boolean> abstractClassInfoCache = CollectionFactory.newConcurrentMap(); + + private final static ThreadLocal<String> CURRENT_PAGE = + ThreadLocal.withInitial(() -> null); public PageSourceImpl(PageLoader pageLoader, ComponentRequestSelectorAnalyzer selectorAnalyzer, ComponentDependencyRegistry componentDependencyRegistry, @@ -178,6 +181,15 @@ public class PageSourceImpl implements PageSource final String className = componentClassResolver.resolvePageNameToClassName(canonicalPageName); if (multipleClassLoaders) { + + if (canonicalPageName.equals(CURRENT_PAGE.get())) + { + throw new IllegalStateException("Infinite method loop detected. Bailing out."); + } + else + { + CURRENT_PAGE.set(canonicalPageName); + } // Avoiding problems in PlasticClassPool.createTransformation() // when the class being loaded has a page superclass @@ -197,7 +209,7 @@ public class PageSourceImpl implements PageSource final String resolvedDependencyPageClass = componentClassResolver.resolvePageNameToClassName(dependencyPageName); if (!canonicalPageName.equals(dependencyPageName) && !className.equals(resolvedDependencyPageClass) - && !isAbstract(className)) + && !isAbstract(dependencyClassName)) { page = getPage(dependencyPageName, invalidateUnknownContext, alreadyProcessed); @@ -358,8 +370,9 @@ public class PageSourceImpl implements PageSource private boolean isAbstract(final String className) { - return abstractClassInfoCache.computeIfAbsent(className, + final Boolean computeIfAbsent = abstractClassInfoCache.computeIfAbsent(className, (s) -> Modifier.isAbstract(ThrowawayClassLoader.load(className).getModifiers())); + return computeIfAbsent; } }
