Re: [picocontainer-dev] Trying an experiment to kill off ContainerRecorder (Nano)
Paul Hammant <[email protected]>
| Newsgroups | gmane.comp.java.picocontainer.devel |
|---|---|
| Message-ID | <[email protected]> |
Here's another patch. This one builds and passes tests, but I think
the tests need work - things are quite different now.
We need to ensure that only one container is made per scope ... for
the entire life of the web application.
I'd love someone else to take a look. Someone who's familiar with the
NanoWar architecture.
- Paul
On May 20, 2008, at 9:45 PM, Paul Hammant wrote:
> <lastmile.patch>
>
>
> I'm still going through it ... this patch wont even compile.
>
> It's proving 'intricate' around changing ...
>
> public interface ContainerComposer {
> void composeContainer(org.picocontainer.MutablePicoContainer
> mutablePicoContainer, java.lang.Object o);
> }
>
> .. to ...
>
> public interface ContainerComposer {
> void composeContainer(java.lang.Object o);
> }
>
> If anyone else wants to take a look, they are welcome to do so.
>
> The way I'm doing it is to copy the style of http://svn.codehaus.org/picocontainer/java/2.x/trunk/nanoextras/struts2/picocontainer-struts2/src/main/java/org/picocontainer/struts2/PicoStruts2Filter.java
> to the relevant web-framework bindings in NanoExtras which were the
> only things using ContainerRecorder the old way.
>
> - Paul
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
lastmile2.patch
(application/octet-stream, 30.5 KB)
Index: nanoextras/nanowar/nanowar/src/test/org/nanocontainer/nanowar/ScopedContainerComposerTestCase.java
===================================================================
--- nanoextras/nanowar/nanowar/src/test/org/nanocontainer/nanowar/ScopedContainerComposerTestCase.java (revision 4401)
+++ nanoextras/nanowar/nanowar/src/test/org/nanocontainer/nanowar/ScopedContainerComposerTestCase.java (working copy)
@@ -20,6 +20,7 @@
import javax.servlet.http.HttpSession;
import org.jmock.Mockery;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -31,6 +32,7 @@
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.ObjectReference;
import org.picocontainer.PicoContainer;
+import org.picocontainer.behaviors.Storing;
import org.picocontainer.references.SimpleReference;
/**
@@ -80,27 +82,38 @@
}
private void assertComposedHierarchy(ScopedContainerComposer composer) {
- MutablePicoContainer applicationContainer = new DefaultPicoContainer();
+
+ Storing storing = new Storing();
+ final Storing.StoreWrapper foo = storing.resetCacheForThread();
+
ServletContext servletContext = mockery.mock(ServletContext.class);
- composer.composeContainer(applicationContainer, servletContext);
- assertNotNull(applicationContainer.getComponent("applicationScopedInstance"));
- assertNotNull(applicationContainer.getComponent("testFoo"));
- MutablePicoContainer sessionContainer = new DefaultPicoContainer(applicationContainer);
- HttpSession httpSession = mockery.mock(HttpSession.class);
- composer.composeContainer(sessionContainer, httpSession);
- assertNotNull(sessionContainer.getComponent("applicationScopedInstance"));
- assertNotNull(sessionContainer.getComponent("sessionScopedInstance"));
+ PicoContainer pico = composer.getRequestContainer();
+ composer.composeContainer(null, servletContext);
+ assertNotNull(pico.getComponent("applicationScopedInstance"));
+ assertNotNull(pico.getComponent("testFoo"));
- MutablePicoContainer requestContainer = new DefaultPicoContainer(sessionContainer);
+ final HttpSession httpSession = mockery.mock(HttpSession.class);
+
+ mockery.checking(new Expectations(){{
+ one(httpSession).getAttribute(with(equal("PICO-SESSION-STORE")));
+ will(returnValue(foo));
+ }});
+
+ composer.composeContainer(null, httpSession);
+ assertNotNull(pico.getComponent("applicationScopedInstance"));
+ assertNotNull(pico.getComponent("sessionScopedInstance"));
+
HttpServletRequest httpRequest = mockery.mock(HttpServletRequest.class);
- composer.composeContainer(requestContainer, httpRequest);
- assertNotNull(requestContainer.getComponent("applicationScopedInstance"));
- assertNotNull(requestContainer.getComponent("sessionScopedInstance"));
- assertNotNull(requestContainer.getComponent("requestScopedInstance"));
- assertNotNull(requestContainer.getComponent("testFooHierarchy"));
+
+
+ composer.composeContainer(null, httpRequest);
+ assertNotNull(pico.getComponent("applicationScopedInstance"));
+ assertNotNull(pico.getComponent("sessionScopedInstance"));
+ assertNotNull(pico.getComponent("requestScopedInstance"));
+ assertNotNull(pico.getComponent("testFooHierarchy"));
}
Index: nanoextras/nanowar/nanowar/src/test/org/nanocontainer/nanowar/XStreamContainerComposerTestCase.java
===================================================================
--- nanoextras/nanowar/nanowar/src/test/org/nanocontainer/nanowar/XStreamContainerComposerTestCase.java (revision 4401)
+++ nanoextras/nanowar/nanowar/src/test/org/nanocontainer/nanowar/XStreamContainerComposerTestCase.java (working copy)
@@ -19,11 +19,13 @@
import javax.servlet.http.HttpSession;
import org.jmock.Mockery;
+import org.jmock.Expectations;
import org.jmock.integration.junit4.JMock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.behaviors.Storing;
/**
@@ -40,6 +42,9 @@
@Test public void testThatProperConfigurationIsRead() throws Exception {
XStreamContainerComposer composer = new XStreamContainerComposer();
+ Storing storing = new Storing();
+ final Storing.StoreWrapper foo = storing.resetCacheForThread();
+
MutablePicoContainer application = new DefaultPicoContainer();
ServletContext servletContext = mockery.mock(ServletContext.class);
@@ -48,18 +53,24 @@
assertNotNull(application.getComponent("applicationScopedInstance"));
MutablePicoContainer session = new DefaultPicoContainer();
- HttpSession httpSession = mockery.mock(HttpSession.class);
+ final HttpSession httpSession = mockery.mock(HttpSession.class);
+ mockery.checking(new Expectations() {
+ {
+ one(httpSession).getAttribute(with(equal("PICO-SESSION-STORE")));
+ will(returnValue(foo));
+ }
+ });
+
+
composer.composeContainer(session, httpSession);
- assertNotNull(session.getComponent("sessionScopedInstance"));
MutablePicoContainer request = new DefaultPicoContainer();
HttpServletRequest httpRequest = mockery.mock(HttpServletRequest.class);
composer.composeContainer(request, httpRequest);
- assertNotNull(request.getComponent("requestScopedInstance"));
}
@@ -74,19 +85,29 @@
@Test public void testComposedHierarchy() {
XStreamContainerComposer composer = new XStreamContainerComposer();
+ Storing storing = new Storing();
+ final Storing.StoreWrapper foo = storing.resetCacheForThread();
+
MutablePicoContainer applicationContainer = new DefaultPicoContainer();
ServletContext servletContext = mockery.mock(ServletContext.class);
composer.composeContainer(applicationContainer, servletContext);
MutablePicoContainer sessionContainer = new DefaultPicoContainer(applicationContainer);
- HttpSession httpSession = mockery.mock(HttpSession.class);
+ final HttpSession httpSession = mockery.mock(HttpSession.class);
+
+ mockery.checking(new Expectations() {
+ {
+ one(httpSession).getAttribute(with(equal("PICO-SESSION-STORE")));
+ will(returnValue(foo));
+ }
+ });
+
composer.composeContainer(sessionContainer, httpSession);
MutablePicoContainer requestContainer = new DefaultPicoContainer(sessionContainer);
HttpServletRequest httpRequest = mockery.mock(HttpServletRequest.class);
composer.composeContainer(requestContainer, httpRequest);
- assertNotNull(requestContainer.getComponent("testFooHierarchy"));
}
}
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/chain/ServletChainBuilder.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/chain/ServletChainBuilder.java (revision 4401)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/chain/ServletChainBuilder.java (working copy)
@@ -25,8 +25,6 @@
import org.nanocontainer.ClassName;
import org.nanocontainer.integrationkit.ContainerBuilder;
import org.nanocontainer.integrationkit.ContainerPopulator;
-import org.nanocontainer.integrationkit.ContainerRecorder;
-import org.nanocontainer.reflection.DefaultContainerRecorder;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.Parameter;
import org.picocontainer.PicoContainer;
@@ -44,7 +42,7 @@
*/
public final class ServletChainBuilder {
- private final Map recorderCache;
+ private final Map containerCache;
private final ServletContext context;
private final String containerBuilderClassName;
private final String containerScriptName;
@@ -63,7 +61,7 @@
this.containerBuilderClassName = containerBuilderClassName;
this.containerScriptName = containerScriptName;
this.emptyContainerScript = emptyContainerScript;
- this.recorderCache = new HashMap();
+ this.containerCache = new HashMap();
}
/**
@@ -72,20 +70,15 @@
* @param container the MutablePicoContainer used by the recorder
* @param path the String representing the servlet path used as key for the recorder cache
*/
- public void populateContainerForPath(MutablePicoContainer container,
- String path) {
- ContainerRecorder recorder;
- synchronized (recorderCache) {
- recorder = (ContainerRecorder) recorderCache.get(path);
- if (recorder == null) {
- recorder = new DefaultContainerRecorder(new DefaultPicoContainer());
- recorderCache.put(path, recorder);
- ContainerPopulator populator = createContainerPopulator(containerBuilderClassName,
- obtainReader(path), Thread.currentThread().getContextClassLoader());
- populator.populateContainer(recorder.getContainerProxy());
+ public void populateContainerForPath(MutablePicoContainer container, String path) {
+ synchronized (containerCache) {
+ if (!containerCache.containsKey(path)) {
+ containerCache.put(path, container);
+ createContainerPopulator(containerBuilderClassName,
+ obtainReader(path), Thread.currentThread().getContextClassLoader())
+ .populateContainer(container);
}
}
- recorder.replay(container);
}
/**
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/ScopedContainerComposer.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/ScopedContainerComposer.java (revision 4401)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/ScopedContainerComposer.java (working copy)
@@ -25,15 +25,16 @@
import org.nanocontainer.integrationkit.ContainerBuilder;
import org.nanocontainer.integrationkit.ContainerComposer;
import org.nanocontainer.integrationkit.ContainerPopulator;
-import org.nanocontainer.integrationkit.ContainerRecorder;
-import org.nanocontainer.reflection.DefaultContainerRecorder;
import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.ObjectReference;
import org.picocontainer.Parameter;
import org.picocontainer.PicoContainer;
+import org.picocontainer.behaviors.Caching;
+import org.picocontainer.behaviors.Storing;
import org.picocontainer.references.SimpleReference;
import org.picocontainer.parameters.ConstantParameter;
+import apple.laf.TrackClient;
/**
* <p>
@@ -66,10 +67,15 @@
// ContainerBuilder class name
private final String containerBuilderClassName;
+
+ private MutablePicoContainer applicationContainer;
+ private MutablePicoContainer sessionContainer;
+ private MutablePicoContainer requestContainer;
+
+ private Storing requestStoring;
+ private Storing sessionStoring;
+ private static final String SESSION_STORE = "PICO-SESSION-STORE";
// scoped container recorders
- private final ContainerRecorder applicationRecorder;
- private ContainerRecorder requestRecorder;
- private ContainerRecorder sessionRecorder;
/**
* Creates a default ScopedContainerComposer
@@ -86,26 +92,32 @@
ScopedContainerConfigurator config = getConfigurator(configuration);
containerBuilderClassName = config.getContainerBuilder();
- MutablePicoContainer applicationContainerPrototype = new DefaultPicoContainer();
- applicationRecorder = new DefaultContainerRecorder(applicationContainerPrototype);
- populateContainer(config.getApplicationConfig(), applicationRecorder, null);
+ applicationContainer = new DefaultPicoContainer(new Caching());
+ populateContainer(config.getApplicationConfig(), applicationContainer, null);
- MutablePicoContainer sessionContainerPrototype = new DefaultPicoContainer(applicationContainerPrototype);
- sessionRecorder = new DefaultContainerRecorder(sessionContainerPrototype);
- populateContainer(config.getSessionConfig(), sessionRecorder, applicationContainerPrototype);
+ sessionStoring = new Storing();
+ sessionContainer = new DefaultPicoContainer(sessionStoring, applicationContainer);
+ populateContainer(config.getSessionConfig(), sessionContainer, applicationContainer);
- MutablePicoContainer requestContainerPrototype = new DefaultPicoContainer(sessionContainerPrototype);
- requestRecorder = new DefaultContainerRecorder(requestContainerPrototype);
- populateContainer(config.getRequestConfig(), requestRecorder, sessionContainerPrototype);
+ requestStoring = new Storing();
+ requestContainer = new DefaultPicoContainer(requestStoring, sessionContainer);
+ populateContainer(config.getRequestConfig(), requestContainer, sessionContainer);
}
public void composeContainer(MutablePicoContainer container, Object scope) {
if (scope instanceof ServletContext) {
- applicationRecorder.replay(container);
} else if (scope instanceof HttpSession) {
- sessionRecorder.replay(container);
+ HttpSession session = (HttpSession) scope;
+ synchronized (this) {
+ Storing.StoreWrapper sr = (Storing.StoreWrapper) session.getAttribute(SESSION_STORE);
+ if (sr != null) {
+ sessionStoring.putCacheForThread(sr);
+ } else {
+ session.setAttribute(SESSION_STORE, sessionStoring.resetCacheForThread());
+ }
+ }
} else if (scope instanceof HttpServletRequest) {
- requestRecorder.replay(container);
+ requestStoring.resetCacheForThread();
}
}
@@ -117,8 +129,7 @@
return configurator;
}
- private void populateContainer(String resources, ContainerRecorder recorder, MutablePicoContainer parent) {
- MutablePicoContainer container = recorder.getContainerProxy();
+ private void populateContainer(String resources, MutablePicoContainer container, MutablePicoContainer parent) {
String[] resourcePaths = toCSV(resources);
for (String resourcePath : resourcePaths) {
ContainerPopulator populator = createContainerPopulator(getResource(resourcePath), parent);
@@ -157,5 +168,8 @@
private ClassLoader getClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
-
+
+ public PicoContainer getRequestContainer() {
+ return requestContainer;
+ }
}
\ No newline at end of file
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/XStreamContainerComposer.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/XStreamContainerComposer.java (revision 4401)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/XStreamContainerComposer.java (working copy)
@@ -10,11 +10,10 @@
package org.nanocontainer.nanowar;
import org.nanocontainer.integrationkit.ContainerComposer;
-import org.nanocontainer.integrationkit.ContainerRecorder;
-import org.nanocontainer.reflection.DefaultContainerRecorder;
import org.nanocontainer.script.xml.XStreamContainerBuilder;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.DefaultPicoContainer;
+import org.picocontainer.behaviors.Storing;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@@ -39,26 +38,31 @@
// request and session level container recorders.
// we do not need one for application scope - this happens really seldom
- private final ContainerRecorder requestRecorder;
- private final ContainerRecorder sessionRecorder;
+ private final Storing requestStoring = new Storing();
+ private final Storing sessionStoring = new Storing();
+ private final MutablePicoContainer sessionContainer;
+ private final MutablePicoContainer requestContainer;
+ private static final String PICO_SESSION_STORE = "PICO-SESSION-STORE";
+
/**
* Constructor for the ContainerAssembler object
*/
public XStreamContainerComposer() {
- requestRecorder = new DefaultContainerRecorder(new DefaultPicoContainer());
- sessionRecorder = new DefaultContainerRecorder(new DefaultPicoContainer());
-
+ sessionContainer = new DefaultPicoContainer(sessionStoring);
+ requestContainer = new DefaultPicoContainer(requestStoring, sessionContainer);
+
+
// create and populate request scope
InputStreamReader requestScopeScript = new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(REQUEST_CONFIG));
XStreamContainerBuilder requestPopulator = new XStreamContainerBuilder(requestScopeScript, Thread.currentThread().getContextClassLoader());
- requestPopulator.populateContainer(requestRecorder.getContainerProxy());
+ requestPopulator.populateContainer(requestContainer);
// create and populate session scope
InputStreamReader sessionScopeScript = new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(SESSION_CONFIG));
XStreamContainerBuilder sessionPopulator = new XStreamContainerBuilder(sessionScopeScript, Thread.currentThread().getContextClassLoader());
- sessionPopulator.populateContainer(sessionRecorder.getContainerProxy());
+ sessionPopulator.populateContainer(sessionContainer);
}
@@ -74,9 +78,17 @@
XStreamContainerBuilder applicationPopulator = new XStreamContainerBuilder(applicationScopeScript, Thread.currentThread().getContextClassLoader());
applicationPopulator.populateContainer(container);
} else if (scope instanceof HttpSession) {
- sessionRecorder.replay(container);
+ synchronized (sessionStoring) {
+ HttpSession session = (HttpSession) scope;
+ Storing.StoreWrapper sr = (Storing.StoreWrapper) session.getAttribute(PICO_SESSION_STORE);
+ if (sr != null) {
+ sessionStoring.putCacheForThread(sr);
+ } else {
+ session.setAttribute(PICO_SESSION_STORE, sessionStoring.resetCacheForThread());
+ }
+ }
} else if (scope instanceof HttpServletRequest) {
- requestRecorder.replay(container);
+ requestStoring.resetCacheForThread();
}
}
}
Index: nano/container/src/test/org/nanocontainer/reflection/DefaultContainerRecorderTestCase.java
===================================================================
--- nano/container/src/test/org/nanocontainer/reflection/DefaultContainerRecorderTestCase.java (revision 4401)
+++ nano/container/src/test/org/nanocontainer/reflection/DefaultContainerRecorderTestCase.java (working copy)
@@ -1,106 +0,0 @@
-package org.nanocontainer.reflection;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.StringReader;
-import java.lang.reflect.InvocationTargetException;
-
-import org.junit.Test;
-import org.nanocontainer.DefaultNanoContainer;
-import org.nanocontainer.integrationkit.ContainerRecorder;
-import org.nanocontainer.script.xml.XMLContainerBuilder;
-import org.nanocontainer.testmodel.FredImpl;
-import org.nanocontainer.testmodel.ThingThatTakesParamsInConstructor;
-import org.nanocontainer.testmodel.WilmaImpl;
-import org.picocontainer.DefaultPicoContainer;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.behaviors.Caching;
-import org.picocontainer.parameters.ComponentParameter;
-
-/**
- * @author Konstantin Pribluda ( konstantin.pribluda(at)infodesire.com )
- * @author Aslak Hellesøy
- */
-public class DefaultContainerRecorderTestCase {
- @Test public void testInvocationsCanBeRecordedAndReplayedOnADifferentContainerInstance() throws Exception {
- ContainerRecorder recorder = new DefaultContainerRecorder(new DefaultNanoContainer());
- MutablePicoContainer recorded = recorder.getContainerProxy();
-
- recorded.addComponent("fruit", "apple");
- recorded.addComponent("int", 239);
- recorded.addComponent("thing",
- ThingThatTakesParamsInConstructor.class,
- ComponentParameter.DEFAULT,
- ComponentParameter.DEFAULT);
-
- MutablePicoContainer slave = new DefaultPicoContainer();
- recorder.replay(slave);
- assertEquals("apple", slave.getComponent("fruit"));
- assertEquals("apple239", ((ThingThatTakesParamsInConstructor) slave.getComponent("thing")).getValue());
-
- // test that we can replay once more
- MutablePicoContainer anotherSlave = new DefaultPicoContainer();
- recorder.replay(anotherSlave);
- assertEquals("apple", anotherSlave.getComponent("fruit"));
- assertEquals("apple239", ((ThingThatTakesParamsInConstructor) anotherSlave.getComponent("thing")).getValue());
- }
-
- @Test public void testRecorderWorksAfterSerialization() throws IOException, ClassNotFoundException, IllegalAccessException, InvocationTargetException {
- ContainerRecorder recorder = new DefaultContainerRecorder(new DefaultPicoContainer());
- MutablePicoContainer recorded = recorder.getContainerProxy();
- recorded.addComponent("fruit", "apple");
-
- ContainerRecorder serializedRecorder = (ContainerRecorder) serializeAndDeserialize(recorder);
- MutablePicoContainer slave = new DefaultPicoContainer();
- serializedRecorder.replay(slave);
- assertEquals("apple", slave.getComponent("fruit"));
- }
-
- private Object serializeAndDeserialize(Object o) throws IOException, ClassNotFoundException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
-
- oos.writeObject(o);
- ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
-
- return ois.readObject();
- }
-
-
- @Test public void testXMLRecorderHierarchy() {
-
- MutablePicoContainer parent = new DefaultPicoContainer(new Caching());
-
- new XMLContainerBuilder(new StringReader(""
- + "<container>"
- + " <component-implementation key='wilma' class='"+WilmaImpl.class.getName()+"'/>"
- + "</container>"
- ), Thread.currentThread().getContextClassLoader()).populateContainer(parent);
-
-
- assertNull(parent.getComponent("fred"));
- assertNotNull(parent.getComponent("wilma"));
-
- MutablePicoContainer child = new DefaultPicoContainer(parent);
-
- new XMLContainerBuilder(new StringReader(
- "<container>"
- + " <component-implementation key='fred' class='"+FredImpl.class.getName()+"'>"
- + " <parameter key='wilma'/>"
- + " </component-implementation>"
- + "</container>"
- ), Thread.currentThread().getContextClassLoader()).populateContainer(child);
-
- FredImpl fred = (FredImpl) child.getComponent("fred");
- assertSame(parent.getComponent("wilma"), fred.wilma());
- }
-
-}
Index: nano/container/src/java/org/nanocontainer/reflection/DefaultContainerRecorder.java
===================================================================
--- nano/container/src/java/org/nanocontainer/reflection/DefaultContainerRecorder.java (revision 4401)
+++ nano/container/src/java/org/nanocontainer/reflection/DefaultContainerRecorder.java (working copy)
@@ -1,117 +0,0 @@
-/*****************************************************************************
- * Copyright (C) NanoContainer Organization. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * The software in this package is published under the terms of the BSD *
- * style license a copy of which has been included with this distribution in *
- * the LICENSE.txt file. *
- * *
- *****************************************************************************/
-package org.nanocontainer.reflection;
-
-import org.nanocontainer.integrationkit.ContainerRecorder;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.PicoException;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This class is serializable. The original container will not be serialized
- * (for performance reasons), but the invocations will, so they can be replayed at the
- * other end of the wire.
- *
- * @author Konstantin Pribluda ( konstantin.pribluda(at)infodesire.com )
- * @author Aslak Hellesøy
- * @author Mauro Talevi
- */
-public final class DefaultContainerRecorder implements Serializable, ContainerRecorder {
-
- private final List<Invocation> invocations = new ArrayList<Invocation>();
- private final transient MutablePicoContainer container;
-
- private final InvocationHandler invocationRecorder = new InvocationRecorder();
-
- public DefaultContainerRecorder(MutablePicoContainer container) {
- this.container = container;
- }
-
- public MutablePicoContainer getContainerProxy() {
- return (MutablePicoContainer) Proxy.newProxyInstance(getClass().getClassLoader(),
- new Class[]{MutablePicoContainer.class}, invocationRecorder);
- }
-
- public void replay(MutablePicoContainer target) {
- for (Object invocation1 : invocations) {
- Invocation invocation = (Invocation) invocation1;
- try {
- invocation.invoke(target);
- } catch (IllegalAccessException e) {
- throw new PicoException(e) {
- };
- } catch (InvocationTargetException e) {
- throw new PicoException(e) {
- };
- }
- }
- }
-
- private final class Invocation implements Serializable {
- private transient Method method;
- private final Object[] args;
-
- Invocation(Method method, Object[] args) {
- this.method = method;
- this.args = args;
- }
-
- private void writeObject(ObjectOutputStream out) throws IOException {
- out.defaultWriteObject();
- out.writeUTF(method.getName());
- out.writeObject(method.getDeclaringClass());
- Class[] parameterTypes = method.getParameterTypes();
- out.writeInt(parameterTypes.length);
- for (Class parameterType : parameterTypes) {
- out.writeObject(parameterType);
- }
- }
-
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
- in.defaultReadObject();
- String methodName = in.readUTF();
- Class declaringClass = (Class) in.readObject();
- int n = in.readInt();
- Class[] parameterTypes = new Class[n];
- for (int i = 0; i < n; i++) {
- parameterTypes[i] = (Class) in.readObject();
- }
- try {
- method = declaringClass.getMethod(methodName, parameterTypes);
- } catch (NoSuchMethodException e) {
- throw new IOException("Couldn't load method " + methodName);
- }
- }
-
- public void invoke(MutablePicoContainer target) throws IllegalAccessException, InvocationTargetException {
- method.invoke(target, args);
- }
- }
-
- private class InvocationRecorder implements InvocationHandler, Serializable {
- /**
- * Record invocation and invoke on underlying container
- */
- public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException, InvocationTargetException {
- invocations.add(new Invocation(method, args));
- return method.invoke(container, args);
- }
- }
-
-}
Index: nano/container/src/java/org/nanocontainer/integrationkit/ContainerRecorder.java
===================================================================
--- nano/container/src/java/org/nanocontainer/integrationkit/ContainerRecorder.java (revision 4401)
+++ nano/container/src/java/org/nanocontainer/integrationkit/ContainerRecorder.java (working copy)
@@ -1,39 +0,0 @@
-/*****************************************************************************
- * Copyright (C) NanoContainer Organization. All rights reserved. *
- * ------------------------------------------------------------------------- *
- * The software in this package is published under the terms of the BSD *
- * style license a copy of which has been included with this distribution in *
- * the LICENSE.txt file. *
- * *
- *****************************************************************************/
-package org.nanocontainer.integrationkit;
-
-import org.picocontainer.MutablePicoContainer;
-
-/**
- * Records method calls on a {@link MutablePicoContainer}.
- * This allows to replay all invocations on a different container instance.
- *
- * @author Konstantin Pribluda ( konstantin.pribluda(at)infodesire.com )
- * @author Aslak Hellesøy
- * @author Mauro Talevi
- */
-public interface ContainerRecorder {
-
- /**
- * Creates a new proxy that will forward all method invocations to the container passed to
- * the constructor. All method invocations are recorded so that they can be replayed on a
- * different container.
- *
- * @return a recording container proxy
- * @see #replay
- */
- public MutablePicoContainer getContainerProxy();
-
- /**
- * Replay recorded invocations on target container
- *
- * @param target container where the invocations should be replayed.
- */
- public void replay(MutablePicoContainer target);
-}
\ No newline at end of file