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.alternatives.issues;
011    
012    import junit.framework.TestCase;
013    
014    import org.picocontainer.MutablePicoContainer;
015    import org.picocontainer.visitors.VerifyingVisitor;
016    import org.picocontainer.behaviors.ImplementationHidingBehaviorFactory;
017    import org.picocontainer.injectors.ConstructorInjectionFactory;
018    import org.picocontainer.DefaultPicoContainer;
019    
020    public class Issue0214TestCase extends TestCase {
021    
022        // This bug as described in the bug report, http://jira.codehaus.org/browse/PICO-214, cannot be reproduced.
023        public void testTheBug() {
024            final MutablePicoContainer pico = new DefaultPicoContainer(new ImplementationHidingBehaviorFactory().forThis(new ConstructorInjectionFactory()));
025            pico.addComponent(A.class);
026    
027            /* This is a workaround for the bug described further down. Normally
028             * this method call should only be needed if specific requirements for
029             * parameters exist, but not if PicoContainer shall resolve the
030             * dependencies itself. However, with ImplementationHidingPicoContainer
031             * this is currently the only way to register a class/interface such
032             * that the automatic resolution works.
033             */
034            pico.addComponent(I1.class, B.class);
035    
036            /* The following addAdapter(Object, Class) of
037             * ImplementationHidingPicoContainer is buggy, as it contains
038             * "ComponentAdapter delegate = componentFactory.createComponentAdapter(componentKey,
039             * componentImplementation, new Parameter[0]);". Instead of "new
040             * Parameter[0]" it should be "null" to have a behaviour consistent to
041             * DefaultPicoContainer, i.e. if PicoContainer shall resolve
042             * dependencies itself.
043             */
044            pico.addComponent(I2.class, C.class);
045    
046            /* The following verify() throws the exception, but is expected not to
047             * throw: "org.picocontainer.PicoVerificationException:
048             * [[org.picocontainer.PicoCompositionException: Either do the
049             * specified parameters not match any of the following constructors:
050             * [public PicoContainerBugTest$C(PicoContainerBugTest$A)] or the
051             * constructors were not accessible for 'class
052             * PicoContainerBugTest$C']]".
053             *
054             * I believe that the error comes this way: In method
055             * getGreediestSatisfiableConstructor parameters are checked against
056             * null and if parameters is not null it is assumed that specific
057             * parameters have been given so that no automatic resolution takes
058             * place. As now during registration instead of "null" falsly "new
059             * Parameter[0]" was stored, this is now interpreted as if only the
060             * nullary constructor shall be used, and if that doesn't exist, the
061             * exception is thrown.
062             */
063            new VerifyingVisitor().traverse(pico);
064        }
065    
066        public static interface I1 {
067        }
068    
069        public static interface I2 {
070        }
071    
072        public static class A {
073            public A() {
074            }
075        }
076    
077        public static class B implements I1 {
078            public B(final A a) {
079            }
080        }
081    
082        public static class C implements I2 {
083            public C(final A a) {
084            }
085        }
086    }