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