001 /***************************************************************************** 002 * Copyright (c) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 * Original code by Joerg Schaible * 009 *****************************************************************************/ 010 011 package org.picocontainer.defaults; 012 013 /** 014 * Abstract utility class to detect recursion cycles. 015 * Derive from this class and implement {@link ThreadLocalCyclicDependencyGuard#run}. 016 * The method will be called by {@link ThreadLocalCyclicDependencyGuard#observe}. Select 017 * an appropriate guard for your scope. Any {@link ObjectReference} can be 018 * used as long as it is initialized with <code>Boolean.FALSE</code>. 019 * 020 * @author Jörg Schaible 021 * @since 1.1 022 */ 023 public abstract class ThreadLocalCyclicDependencyGuard extends ThreadLocal implements CyclicDependencyGuard { 024 025 protected Object initialValue() { 026 return Boolean.FALSE; 027 } 028 029 /** 030 * Derive from this class and implement this function with the functionality 031 * to observe for a dependency cycle. 032 * 033 * @return a value, if the functionality result in an expression, 034 * otherwise just return <code>null</code> 035 */ 036 public abstract Object run(); 037 038 /** 039 * Call the observing function. The provided guard will hold the {@link Boolean} value. 040 * If the guard is already <code>Boolean.TRUE</code> a {@link CyclicDependencyException} 041 * will be thrown. 042 * 043 * @param stackFrame the current stack frame 044 * @return the result of the <code>run</code> method 045 */ 046 public final Object observe(Class stackFrame) { 047 if (Boolean.TRUE.equals(get())) { 048 throw new CyclicDependencyException(stackFrame); 049 } 050 Object result = null; 051 try { 052 set(Boolean.TRUE); 053 result = run(); 054 } catch (final CyclicDependencyException e) { 055 e.push(stackFrame); 056 throw e; 057 } finally { 058 set(Boolean.FALSE); 059 } 060 return result; 061 } 062 }