001    package org.nanocontainer.reflection;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.ByteArrayOutputStream;
005    import java.io.IOException;
006    import java.io.ObjectInputStream;
007    import java.io.ObjectOutputStream;
008    import java.io.Reader;
009    import java.io.StringReader;
010    import java.lang.reflect.InvocationTargetException;
011    
012    import junit.framework.TestCase;
013    
014    import org.nanocontainer.integrationkit.ContainerPopulator;
015    import org.nanocontainer.integrationkit.ContainerRecorder;
016    import org.nanocontainer.script.xml.XMLContainerBuilder;
017    import org.nanocontainer.testmodel.FredImpl;
018    import org.nanocontainer.testmodel.ThingThatTakesParamsInConstructor;
019    import org.nanocontainer.testmodel.Wilma;
020    import org.nanocontainer.testmodel.WilmaImpl;
021    import org.picocontainer.MutablePicoContainer;
022    import org.picocontainer.Parameter;
023    import org.picocontainer.defaults.ComponentParameter;
024    import org.picocontainer.defaults.DefaultPicoContainer;
025    
026    /**
027     * @author Konstantin Pribluda ( konstantin.pribluda(at)infodesire.com )
028     * @author Aslak Hellesøy
029     */
030    public class DefaultContainerRecorderTestCase extends TestCase {
031        public void testInvocationsCanBeRecordedAndReplayedOnADifferentContainerInstance() throws Exception {
032            ContainerRecorder recorder = new DefaultContainerRecorder(new DefaultNanoPicoContainer());
033            MutablePicoContainer recorded = recorder.getContainerProxy();
034    
035            recorded.registerComponentInstance("fruit", "apple");
036            recorded.registerComponentInstance("int", new Integer(239));
037            recorded.registerComponentImplementation("thing",
038                    ThingThatTakesParamsInConstructor.class,
039                    new Parameter[]{
040                        ComponentParameter.DEFAULT,
041                        ComponentParameter.DEFAULT,
042                    });
043    
044            MutablePicoContainer slave = new DefaultPicoContainer();
045            recorder.replay(slave);
046            assertEquals("apple", slave.getComponentInstance("fruit"));
047            assertEquals("apple239", ((ThingThatTakesParamsInConstructor) slave.getComponentInstance("thing")).getValue());
048    
049            // test that we can replay once more
050            MutablePicoContainer anotherSlave = new DefaultPicoContainer();
051            recorder.replay(anotherSlave);
052            assertEquals("apple", anotherSlave.getComponentInstance("fruit"));
053            assertEquals("apple239", ((ThingThatTakesParamsInConstructor) anotherSlave.getComponentInstance("thing")).getValue());
054        }
055    
056        public void testRecorderWorksAfterSerialization() throws IOException, ClassNotFoundException, IllegalAccessException, InvocationTargetException {
057            ContainerRecorder recorder = new DefaultContainerRecorder(new DefaultPicoContainer());
058            MutablePicoContainer recorded = recorder.getContainerProxy();
059            recorded.registerComponentInstance("fruit", "apple");
060    
061            ContainerRecorder serializedRecorder = (ContainerRecorder) serializeAndDeserialize(recorder);
062            MutablePicoContainer slave = new DefaultPicoContainer();
063            serializedRecorder.replay(slave);
064            assertEquals("apple", slave.getComponentInstance("fruit"));
065        }
066    
067        private Object serializeAndDeserialize(Object o) throws IOException, ClassNotFoundException {
068            ByteArrayOutputStream baos = new ByteArrayOutputStream();
069            ObjectOutputStream oos = new ObjectOutputStream(baos);
070    
071            oos.writeObject(o);
072            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
073    
074            return ois.readObject();
075        }
076    
077    
078        public void testXMLRecorderHierarchy() throws ClassNotFoundException {
079            MutablePicoContainer parentPrototype = new DefaultPicoContainer();
080            DefaultContainerRecorder parentRecorder = new DefaultContainerRecorder(parentPrototype);
081            StringReader parentResource = new StringReader("" 
082                    + "<container>" 
083                    + "  <component-implementation key='wilma' class='"+WilmaImpl.class.getName()+"'/>"
084                    + "</container>" 
085                    );
086    
087            populateXMLContainer(parentRecorder, parentResource);
088            MutablePicoContainer parentContainer = parentRecorder.getContainerProxy();
089            assertNull(parentContainer.getComponentInstance("fred"));
090            assertNotNull(parentContainer.getComponentInstance("wilma"));
091    
092            MutablePicoContainer childPrototype = new DefaultPicoContainer(parentPrototype);
093            DefaultContainerRecorder childRecorder = new DefaultContainerRecorder(childPrototype);
094            StringReader childResource = new StringReader("" 
095                    + "<container>" 
096                    + "  <component-implementation key='fred' class='"+FredImpl.class.getName()+"'>"
097                    + "     <parameter key='wilma'/>"  
098                   + "  </component-implementation>"  
099                    + "</container>" 
100                    );
101            populateXMLContainer(childRecorder, childResource);
102            MutablePicoContainer childContainer = childRecorder.getContainerProxy();
103            assertNotNull(childContainer.getComponentInstance("fred"));
104            assertNotNull(childContainer.getComponentInstance("wilma"));
105            FredImpl fred = (FredImpl)childContainer.getComponentInstance("fred");
106            Wilma wilma = (Wilma)childContainer.getComponentInstance("wilma");
107            assertSame(wilma, fred.wilma());
108        }
109        
110        private void populateXMLContainer(ContainerRecorder recorder, Reader resource) {
111            ContainerPopulator populator = new XMLContainerBuilder(resource, Thread.currentThread().getContextClassLoader());
112            populator.populateContainer(recorder.getContainerProxy());
113        }       
114    }