001    package org.picocontainer.defaults.issues;
002    
003    import junit.framework.TestCase;
004    
005    import java.util.List;
006    import java.util.ArrayList;
007    
008    import org.picocontainer.PicoContainer;
009    import org.picocontainer.defaults.ConstructorInjectionComponentAdapterFactory;
010    import org.picocontainer.defaults.DefaultPicoContainer;
011    import org.picocontainer.defaults.SynchronizedComponentAdapterFactory;
012    
013    public class Issue0199TestCase extends TestCase {
014    
015        public static class A {
016            public A(C c) {}
017        }
018    
019        public static class B {
020            public B(C c) {}
021        }
022    
023        public static class C {}
024    
025        class Runner extends Thread {
026            private PicoContainer container;
027            private Object componentKey;
028            private Throwable throwable;
029            private boolean finished;
030    
031            Runner(String name, PicoContainer container, Object componentKey) {
032                super(name);
033                this.container = container;
034                this.componentKey = componentKey;
035            }
036    
037            public void run() {
038                try {
039                    report("Started instantiating " + componentKey.toString());
040                    container.getComponentInstance(componentKey);
041                    report("Finished instantiating " + componentKey.toString());
042                    finished = true;
043                } catch (Throwable t) {
044                    this.throwable = t;
045                }
046            }
047    
048            private void report(String messsage) {
049                System.out.println(getName() + ": " + messsage);
050            }
051    
052            public boolean isFinished() {
053                return finished;
054            }
055    
056            public Throwable getThrowable() {
057                return throwable;
058            }
059        }
060    
061        public void testPicoContainerCausesDeadlock() throws InterruptedException {
062            DefaultPicoContainer container = createContainer();
063            container.registerComponentImplementation("A", A.class);
064            container.registerComponentImplementation("B", B.class);
065            container.registerComponentImplementation("C", C.class);
066    
067            final int THREAD_COUNT = 2;
068            List runnerList = new ArrayList(THREAD_COUNT);
069    
070            for (int i = 0; i < THREAD_COUNT; ++i) {
071                Runner runner = new Runner("Runner " + i, container, (i % 2 == 0) ? "A" : "B");
072                runnerList.add(runner);
073                runner.start();
074            }
075    
076            final long WAIT_TIME = 1000;
077    
078            for (int i = 0; i < THREAD_COUNT; ++i) {
079                Runner runner = (Runner) runnerList.get(i);
080                runner.join(WAIT_TIME);
081                assertTrue("Deadlock occurred", runner.isFinished());
082            }
083        }
084    
085        private DefaultPicoContainer createContainer() {
086            return new DefaultPicoContainer(
087                    new SynchronizedComponentAdapterFactory(
088                            new ConstructorInjectionComponentAdapterFactory()));
089        }
090    }