Re: [picocontainer-dev] While looking at the streamlining of NanoWar ...
Paul Hammant <[email protected]>
| Newsgroups | gmane.comp.java.picocontainer.devel |
|---|---|
| Message-ID | <[email protected]> |
OK here is a from-scratch better attempt to replace the old NanoWar
with a new one leveraging the ThreadLocal magic :-
There is still a much more to do, but you can see the over all design
by looking at :
NanoWarSessionListener.java (rewritten)
NanoWarContextListener.java (rewritten)
and
NewFilter (all new)
if taken to completion, this would mean that a few classes remaining
would be deleted, and much renamed to make it right.
- Paul
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
allnew.patch
(application/octet-stream, 46.1 KB)
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/NewFilter.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/NewFilter.java (revision 0)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/NewFilter.java (revision 0)
@@ -0,0 +1,61 @@
+package org.nanocontainer.nanowar;
+
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.PicoContainer;
+import org.picocontainer.behaviors.Storing;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class NewFilter extends AbstractNanoWarListener implements Filter {
+
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+ public void destroy() {
+ }
+
+ public static ThreadLocal<PicoContainer> currentContainer = new ThreadLocal<PicoContainer>();
+
+ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
+
+ HttpServletRequest httpReq = (HttpServletRequest) req;
+ HttpServletResponse httpResp = (HttpServletResponse) resp;
+ HttpSession session = httpReq.getSession();
+ ServletContext context = session.getServletContext();
+
+ SessionContainerHolder sch = (SessionContainerHolder) context.getAttribute(SessionContainerHolder.class.getName());
+ RequestContainerHolder rch = (RequestContainerHolder) context.getAttribute(RequestContainerHolder.class.getName());
+
+ Storing sessionStoring = sch.getStoring();
+ Storing requestStoring = rch.getStoring();
+
+ SessionStoreHolder ssh = (SessionStoreHolder) session.getAttribute(SessionStoreHolder.class.getName());
+ sessionStoring.putCacheForThread(ssh.getStoreWrapper());
+ requestStoring.resetCacheForThread();
+ rch.getLifecycleStateModel().resetStateModelForThread();
+ rch.getContainer().start();
+
+ currentContainer.set(rch.getContainer());
+
+ filterChain.doFilter(req, resp);
+
+ currentContainer.set(null);
+
+ rch.getContainer().stop();
+ rch.getContainer().dispose();
+ rch.getLifecycleStateModel().invalidateStateModelForThread();
+ sessionStoring.invalidateCacheForThread();
+ requestStoring.invalidateCacheForThread();
+
+ }
+
+}
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/AbstractNanoWarListener.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/AbstractNanoWarListener.java (revision 4422)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/AbstractNanoWarListener.java (working copy)
@@ -25,16 +25,4 @@
*/
public class AbstractNanoWarListener implements Serializable {
- protected PicoContainer buildContainer(ScriptedContainerBuilder builder) {
- ObjectReference containerRef = new SimpleReference();
- builder.buildContainer(containerRef, new SimpleReference(), new SimpleReference(), false);
- return (PicoContainer) containerRef.get();
- }
-
- protected void killContainer(ObjectReference containerRef) {
- ContainerBuilder containerKiller = new DefaultContainerBuilder(null);
- if (containerRef.get() != null) {
- containerKiller.killContainer(containerRef);
- }
- }
}
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/ThreadLocalLifecycleState.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/ThreadLocalLifecycleState.java (revision 0)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/ThreadLocalLifecycleState.java (revision 0)
@@ -0,0 +1,58 @@
+package org.nanocontainer.nanowar;
+
+import org.picocontainer.lifecycle.LifecycleState;
+import org.picocontainer.lifecycle.DefaultLifecycleState;
+
+public class ThreadLocalLifecycleState implements LifecycleState {
+
+ private LifecycleStateThreadLocal tl = new LifecycleStateThreadLocal();
+
+ public void removingComponent() {
+ tl.get().removingComponent();
+ }
+
+ public void starting() {
+ tl.get().starting();
+ }
+
+ public void stopping() {
+ tl.get().stopping();
+ }
+
+ public void stopped() {
+ tl.get().stopped();
+ }
+
+ public boolean isStarted() {
+ return tl.get().isStarted();
+ }
+
+ public void disposing() {
+ tl.get().disposing();
+ }
+
+ public void disposed() {
+ tl.get().disposed();
+ }
+
+ public void putLifecycleStateModelForThread(DefaultLifecycleState lifecycleState) {
+ tl.set(lifecycleState);
+ }
+
+ public DefaultLifecycleState resetStateModelForThread() {
+ DefaultLifecycleState dls = new DefaultLifecycleState();
+ tl.set(dls);
+ return dls;
+ }
+
+ public void invalidateStateModelForThread() {
+ tl.set(null);
+ }
+
+ private static class LifecycleStateThreadLocal extends ThreadLocal<DefaultLifecycleState> {
+ protected DefaultLifecycleState initialValue() {
+ return new DefaultLifecycleState();
+ }
+ }
+
+}
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/ApplicationContainerHolder.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/ApplicationContainerHolder.java (revision 0)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/ApplicationContainerHolder.java (revision 0)
@@ -0,0 +1,16 @@
+package org.nanocontainer.nanowar;
+
+import org.picocontainer.DefaultPicoContainer;
+
+public class ApplicationContainerHolder {
+
+ private final DefaultPicoContainer container;
+
+ public ApplicationContainerHolder(DefaultPicoContainer container) {
+ this.container = container;
+ }
+
+ DefaultPicoContainer getContainer() {
+ return container;
+ }
+}
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/NanoWarSessionListener.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/NanoWarSessionListener.java (revision 4422)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/NanoWarSessionListener.java (working copy)
@@ -20,6 +20,9 @@
import org.nanocontainer.integrationkit.ContainerBuilder;
import org.picocontainer.ObjectReference;
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.lifecycle.DefaultLifecycleState;
+import org.picocontainer.behaviors.Storing;
import org.picocontainer.references.SimpleReference;
/**
@@ -64,6 +67,8 @@
*/
public class NanoWarSessionListener extends AbstractNanoWarListener implements HttpSessionListener, KeyConstants {
+ private static final String PICO_SESSION_LIFECYCLE_STATE_WRAPPER = "PICO-SESSION-LIFECYCLE-STATE-WRAPPER";
+
private ContainerBuilder getBuilder(ServletContext context) {
ObjectReference assemblerRef = new ApplicationScopeReference(context, BUILDER);
return (ContainerBuilder) assemblerRef.get();
@@ -72,42 +77,32 @@
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = event.getSession();
ServletContext context = session.getServletContext();
- ContainerBuilder containerBuilder = getBuilder(context);
- ObjectReference sessionContainerRef = new SessionScopeReference(session, SESSION_CONTAINER);
- ObjectReference webappContainerRef = new ApplicationScopeReference(context, APPLICATION_CONTAINER);
- containerBuilder.buildContainer(sessionContainerRef, webappContainerRef, session, false);
- session.setAttribute(KILLER_HELPER, new SessionContainerKillerHelper() {
- public void valueBound(HttpSessionBindingEvent bindingEvent) {
- HttpSession session = bindingEvent.getSession();
- containerRef = new SimpleReference();
- containerRef.set(new SessionScopeReference(session, SESSION_CONTAINER).get());
- }
+ SessionContainerHolder sch = (SessionContainerHolder) context.getAttribute(SessionContainerHolder.class.getName());
+ Storing sessionStoring = sch.getStoring();
+ ThreadLocalLifecycleState tlLifecycleState = sch.getLifecycleStateModel();
- public void valueUnbound(HttpSessionBindingEvent event) {
- try {
- killContainer(containerRef);
- } catch (IllegalStateException e) {
- //
- //Some servlet containers (Jetty) call contextDestroyed(ServletContextEvent event)
- //and then afterwards call valueUnbound(HttpSessionBindingEvent event).
+ session.setAttribute(SessionStoreHolder.class.getName(), new SessionStoreHolder(sessionStoring.resetCacheForThread(), tlLifecycleState.resetStateModelForThread()));
- //contextDestroyed will kill the top level (app level) pico container which will
- //cascade stop() down to the session children.
-
- //This means that when valueUnbound is called later, the session level container will
- //already be stopped.
- //
- }
- }
- });
+ sch.getContainer().start();
}
- public void sessionDestroyed(HttpSessionEvent se) {
- // no implementation - session scoped container killed by SessionContainerKillerHelper
- }
+ public void sessionDestroyed(HttpSessionEvent event) {
+ HttpSession session = event.getSession();
+ ServletContext context = session.getServletContext();
- private abstract class SessionContainerKillerHelper implements HttpSessionBindingListener, Serializable {
- transient SimpleReference containerRef;
+ SessionStoreHolder ssh = (SessionStoreHolder) session.getAttribute(SessionStoreHolder.class.getName());
+
+ SessionContainerHolder sch = (SessionContainerHolder) context.getAttribute(SessionContainerHolder.class.getName());
+ ThreadLocalLifecycleState tlLifecycleState = sch.getLifecycleStateModel();
+
+ sch.getStoring().putCacheForThread(ssh.getStoreWrapper());
+ tlLifecycleState.putLifecycleStateModelForThread((DefaultLifecycleState) session.getAttribute(PICO_SESSION_LIFECYCLE_STATE_WRAPPER));
+
+ sch.getContainer().stop();
+ sch.getContainer().dispose();
+ sch.getStoring().invalidateCacheForThread();
+
}
+
}
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/NanoWarContextListener.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/NanoWarContextListener.java (revision 4423)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/NanoWarContextListener.java (working copy)
@@ -11,10 +11,9 @@
import java.io.InputStreamReader;
import java.io.Reader;
-import java.io.StringReader;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.ArrayList;
+import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
@@ -24,17 +23,13 @@
import org.nanocontainer.DefaultNanoContainer;
import org.nanocontainer.NanoContainer;
import org.nanocontainer.integrationkit.ContainerBuilder;
-import org.nanocontainer.integrationkit.ContainerComposer;
-import org.nanocontainer.integrationkit.DefaultContainerBuilder;
-import org.nanocontainer.script.ScriptBuilderResolver;
-import org.nanocontainer.script.ScriptedContainerBuilderFactory;
-import org.picocontainer.ComponentAdapter;
+import org.nanocontainer.integrationkit.ContainerPopulator;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.ObjectReference;
-import org.picocontainer.PicoCompositionException;
-import org.picocontainer.PicoContainer;
-import org.picocontainer.containers.PropertiesPicoContainer;
-import org.picocontainer.containers.SystemPropertiesPicoContainer;
+import org.picocontainer.DefaultPicoContainer;
+import org.picocontainer.lifecycle.LifecycleState;
+import org.picocontainer.behaviors.Caching;
+import org.picocontainer.behaviors.Storing;
import org.picocontainer.parameters.ConstantParameter;
import org.picocontainer.references.SimpleReference;
@@ -49,24 +44,23 @@
* <p>
* The containers are configured via context-params in web.xml, in two ways:
* <ol>
- * <li>A NanoContainer script via a parameter whose name is nanocontainer.<language>,
- * where <language> is one of the supported scripting languages,
- * see {@link org.nanocontainer.script.ScriptedContainerBuilderFactory ScriptedContainerBuilderFactory}.
- * The parameter value can be either an inlined script (enclosed in <![CDATA[]>), or a resource path for
- * the script (relative to the webapp context).
- * </li>
- * <li>A ContainerComposer class via the parameter name
- * {@link KeyConstants#CONTAINER_COMPOSER CONTAINER_COMPOSER},
- * which can be configured via an optional parameter
- * {@link KeyConstants#CONTAINER_COMPOSER_CONFIGURATION CONTAINER_COMPOSER_CONFIGURATION}.
- * </li>
+ * <li>A NanoContainer script via a parameter whose name is nanocontainer.<language>,
+ * where <language> is one of the supported scripting languages,
+ * see {@link org.nanocontainer.script.ScriptedContainerBuilderFactory ScriptedContainerBuilderFactory}.
+ * The parameter value can be either an inlined script (enclosed in <![CDATA[]>), or a resource path for
+ * the script (relative to the webapp context).
+ * </li>
+ * <li>A ContainerComposer class via the parameter name
+ * {@link KeyConstants#CONTAINER_COMPOSER CONTAINER_COMPOSER},
+ * which can be configured via an optional parameter
+ * {@link KeyConstants#CONTAINER_COMPOSER_CONFIGURATION CONTAINER_COMPOSER_CONFIGURATION}.
+ * </li>
* </ol>
* </p>
- * <p><b>Note:</b> if one is interested in both application-scoped and session-scoped components, the
+ * <p><b>Note:</b> if one is interested in both application-scoped and session-scoped components, the
* {@link org.nanocontainer.nanowar.ServletContainerListener} should be configured in the web.xml.
* </p>
- * @see org.nanocontainer.nanowar.NanoWarSessionListener
- * @see org.nanocontainer.nanowar.ServletContainerListener
+ *
* @author Michael Rimov
* @author Joe Walnes
* @author Aslak Hellesøy
@@ -74,106 +68,92 @@
* @author Paul Hammant
* @author Mauro Talevi
* @author Konstantin Pribluda
+ * @see org.nanocontainer.nanowar.NanoWarSessionListener
+ * @see org.nanocontainer.nanowar.ServletContainerListener
*/
@SuppressWarnings("serial")
public class NanoWarContextListener extends AbstractNanoWarListener implements ServletContextListener, KeyConstants {
- /**
- * handle context initialisation. we need to create container
- * and store it into proper reference
- */
+ /**
+ * handle context initialisation. we need to create container
+ * and store it into proper reference
+ */
public void contextInitialized(ServletContextEvent event) {
ServletContext context = event.getServletContext();
- ContainerBuilder containerBuilder = createContainerBuilder(context);
- ObjectReference<ContainerBuilder> builderRef = new ApplicationScopeReference<ContainerBuilder>(context, BUILDER);
- builderRef.set(containerBuilder);
- SimpleReference<PicoContainer> parentRef = new SimpleReference<PicoContainer>();
+ DefaultPicoContainer sessionContainer;
+ DefaultPicoContainer requestContainer;
- // check whether we have to provide system roperties container
- if(context.getInitParameter(SYSTEM_PROPERTIES_CONTAINER) != null) {
- parentRef.set(new SystemPropertiesPicoContainer());
- }
-
- // maybe there are properties specified?
- String propertiesResource = context.getInitParameter(PROPERTIES_CONTAINER);
- if(propertiesResource != null) {
- Properties properties = new Properties();
- try {
- properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(propertiesResource));
- } catch (IOException e) {
- event.getServletContext().log(e.getMessage(), e);
- throw new PicoCompositionException(e);
- }
- parentRef.set(new PropertiesPicoContainer(properties,parentRef.get()));
- }
-
- ObjectReference containerRef = new ApplicationScopeReference(context, APPLICATION_CONTAINER);
- containerBuilder.buildContainer(containerRef, parentRef, context, false);
+ Storing sessionStoring = new Storing();
+ Storing requestStoring = new Storing();
+
+ DefaultPicoContainer appContainer = new DefaultPicoContainer(new Caching());
+ appContainer.setName("application");
+ String builderClassName = context.getInitParameter("container-builder-class") ;
+ populateContainer(appResources, new ApplicationContainerHolder(appContainer), null, builderClassName);
+
+ context.setAttribute(ApplicationContainerHolder.class.getName(), new ApplicationContainerHolder(appContainer));
+
+ sessionStoring = new Storing();
+ sessionContainer = new DefaultPicoContainer(sessionStoring, appContainer);
+ sessionContainer.setName("session");
+ LifecycleState sessionStateModel = new ThreadLocalLifecycleState();
+ sessionContainer.setLifecycleState(sessionStateModel);
+ populateContainer(sessionResources, sessionContainer, appContainer, builderClassName);
+
+ context.setAttribute(SessionContainerHolder.class.getName(), new SessionContainerHolder(sessionContainer, sessionStoring, sessionStateModel));
+
+ requestStoring = new Storing();
+ requestContainer = new DefaultPicoContainer(requestStoring, sessionContainer);
+ requestContainer.setName("request");
+ LifecycleState requestStateModel = new ThreadLocalLifecycleState();
+ requestContainer.setLifecycleState(requestStateModel);
+ populateContainer(requestResources, requestContainer, sessionContainer, builderClassName);
+
+ context.setAttribute(RequestContainerHolder.class.getName(), new RequestContainerHolder(requestContainer, requestStoring, requestStateModel));
+
}
- /**
- * TODO: this is kind of scary and has big confusion potential ( i.e.: collision with properties specification )
- * @param context
- * @return
- */
- private ContainerBuilder createContainerBuilder(ServletContext context) {
- Enumeration initParameters = context.getInitParameterNames();
- while (initParameters.hasMoreElements()) {
- String initParameter = (String) initParameters.nextElement();
- if (initParameter.startsWith(NANOCONTAINER_PREFIX)) {
- String builderClassName = getBuilderClassName(initParameter);
- String script = context.getInitParameter(initParameter);
- Reader scriptReader;
- if (script.trim().startsWith("/") && !(script.trim().startsWith("//") || script.trim().startsWith("/*"))) {
- // the script isn't inlined, but in a separate file.
- scriptReader = new InputStreamReader(context.getResourceAsStream(script));
- } else {
- scriptReader = new StringReader(script);
- }
- ScriptedContainerBuilderFactory scriptedContainerBuilderFactory = new ScriptedContainerBuilderFactory(scriptReader, builderClassName, Thread.currentThread().getContextClassLoader());
- return scriptedContainerBuilderFactory.getContainerBuilder();
- }
- if (initParameter.equals(CONTAINER_COMPOSER)) {
- ContainerComposer containerComposer = createContainerComposer(context);
- return new DefaultContainerBuilder(containerComposer);
- }
- }
- throw new PicoCompositionException("Couldn't create a builder from context parameters in web.xml");
+ public void contextDestroyed(ServletContextEvent event) {
+ ServletContext context = event.getServletContext();
+ ApplicationContainerHolder ach = (ApplicationContainerHolder) context.getAttribute(ApplicationContainerHolder.class.getName());
+ ach.getContainer().stop();
+ ach.getContainer().dispose();
}
- private String getBuilderClassName(String scriptName){
- String extension = scriptName.substring(scriptName.lastIndexOf('.'));
- ScriptBuilderResolver resolver = new ScriptBuilderResolver();
- return resolver.getBuilderClassName(extension);
+ private void populateContainer(String resources, MutablePicoContainer container, MutablePicoContainer parent, String containerBuilderClassName) {
+ String[] resourcePaths = toCSV(resources);
+ for (String resourcePath : resourcePaths) {
+ ContainerPopulator populator = createContainerPopulator(getResource(resourcePath), parent, containerBuilderClassName);
+ populator.populateContainer(container);
+ }
}
- private ContainerComposer createContainerComposer(ServletContext context) {
- String containerComposerClassName = context.getInitParameter(CONTAINER_COMPOSER);
- // disposable container used to instantiate the ContainerComposer
- NanoContainer nanoContainer = new DefaultNanoContainer(Thread.currentThread().getContextClassLoader());
- String script = context.getInitParameter(CONTAINER_COMPOSER_CONFIGURATION);
- PicoContainer picoConfiguration = null;
- if ( script != null ){
- Reader scriptReader = new InputStreamReader(context.getResourceAsStream(script));
- String builderClassName = getBuilderClassName(script);
- ScriptedContainerBuilderFactory scriptedContainerBuilderFactory = new ScriptedContainerBuilderFactory(scriptReader, builderClassName, Thread.currentThread().getContextClassLoader());
- picoConfiguration = buildContainer(scriptedContainerBuilderFactory.getContainerBuilder());
+ private static final String COMMA = ",";
+
+ private String[] toCSV(String resources) {
+ StringTokenizer st = new StringTokenizer(resources, COMMA);
+ List<String> tokens = new ArrayList<String>();
+ while (st.hasMoreTokens()) {
+ tokens.add(st.nextToken().trim());
}
- ComponentAdapter componentAdapter;
- if ( picoConfiguration != null ){
- componentAdapter = nanoContainer.addComponent(containerComposerClassName, new ClassName(containerComposerClassName), new ConstantParameter(picoConfiguration)).getComponentAdapter(containerComposerClassName);
- } else {
- ClassName className = new ClassName(containerComposerClassName);
- MutablePicoContainer mutablePicoContainer = nanoContainer.addComponent(className);
- componentAdapter = mutablePicoContainer.getComponentAdapter(className);
- }
- return (ContainerComposer) componentAdapter.getComponentInstance(nanoContainer);
+ return tokens.toArray(new String[tokens.size()]);
}
- public void contextDestroyed(ServletContextEvent event) {
- ServletContext context = event.getServletContext();
- ObjectReference containerRef = new ApplicationScopeReference(context, APPLICATION_CONTAINER);
- killContainer(containerRef);
+ private Reader getResource(String resource) {
+ return new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(resource));
}
+
+ private ContainerPopulator createContainerPopulator(Reader reader, MutablePicoContainer parent, String containerBuilderClassName) {
+ NanoContainer nano = new DefaultNanoContainer(Thread.currentThread().getContextClassLoader());
+ nano.addComponent(containerBuilderClassName,
+ new ClassName(containerBuilderClassName), new ConstantParameter(reader),
+ new ConstantParameter(Thread.currentThread().getContextClassLoader()));
+ ContainerBuilder containerBuilder = (ContainerBuilder) nano
+ .getComponent(containerBuilderClassName);
+ ObjectReference parentRef = new SimpleReference();
+ parentRef.set(parent);
+ containerBuilder.buildContainer(new SimpleReference(), parentRef, null, false);
+ return (ContainerPopulator) containerBuilder;
+ }
}
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/SessionContainerHolder.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/SessionContainerHolder.java (revision 0)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/SessionContainerHolder.java (revision 0)
@@ -0,0 +1,30 @@
+package org.nanocontainer.nanowar;
+
+import org.picocontainer.DefaultPicoContainer;
+import org.picocontainer.lifecycle.LifecycleState;
+import org.picocontainer.behaviors.Storing;
+
+public class SessionContainerHolder {
+
+ private final DefaultPicoContainer container;
+ private final Storing storing;
+ private final ThreadLocalLifecycleState lifecycleState;
+
+ public SessionContainerHolder(DefaultPicoContainer container, Storing storing, ThreadLocalLifecycleState lifecycleState) {
+ this.container = container;
+ this.storing = storing;
+ this.lifecycleState = lifecycleState;
+ }
+
+ DefaultPicoContainer getContainer() {
+ return container;
+ }
+
+ Storing getStoring() {
+ return storing;
+ }
+
+ ThreadLocalLifecycleState getLifecycleStateModel() {
+ return lifecycleState;
+ }
+}
\ No newline at end of file
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/RequestContainerHolder.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/RequestContainerHolder.java (revision 0)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/RequestContainerHolder.java (revision 0)
@@ -0,0 +1,30 @@
+package org.nanocontainer.nanowar;
+
+import org.picocontainer.DefaultPicoContainer;
+import org.picocontainer.lifecycle.LifecycleState;
+import org.picocontainer.behaviors.Storing;
+
+public class RequestContainerHolder {
+
+ private final DefaultPicoContainer container;
+ private final Storing storing;
+ private final ThreadLocalLifecycleState lifecycleState;
+
+ public RequestContainerHolder(DefaultPicoContainer container, Storing storing, ThreadLocalLifecycleState lifecycleState) {
+ this.container = container;
+ this.storing = storing;
+ this.lifecycleState = lifecycleState;
+ }
+
+ DefaultPicoContainer getContainer() {
+ return container;
+ }
+
+ Storing getStoring() {
+ return storing;
+ }
+
+ ThreadLocalLifecycleState getLifecycleStateModel() {
+ return lifecycleState;
+ }
+}
\ No newline at end of file
Index: nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/SessionStoreHolder.java
===================================================================
--- nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/SessionStoreHolder.java (revision 0)
+++ nanoextras/nanowar/nanowar/src/java/org/nanocontainer/nanowar/SessionStoreHolder.java (revision 0)
@@ -0,0 +1,24 @@
+package org.nanocontainer.nanowar;
+
+import org.picocontainer.behaviors.Storing;
+import org.picocontainer.lifecycle.DefaultLifecycleState;
+
+public class SessionStoreHolder {
+ private final Storing.StoreWrapper storeWrapper;
+ private final DefaultLifecycleState defaultLifecycleState;
+
+ public SessionStoreHolder(Storing.StoreWrapper storeWrapper,
+ DefaultLifecycleState defaultLifecycleState) {
+
+ this.storeWrapper = storeWrapper;
+ this.defaultLifecycleState = defaultLifecycleState;
+ }
+
+ Storing.StoreWrapper getStoreWrapper() {
+ return storeWrapper;
+ }
+
+ DefaultLifecycleState getDefaultLifecycleState() {
+ return defaultLifecycleState;
+ }
+}
Index: nanoextras/nanowar/pom.xml
===================================================================
--- nanoextras/nanowar/pom.xml (revision 4422)
+++ nanoextras/nanowar/pom.xml (working copy)
@@ -95,7 +95,7 @@
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer-gems</artifactId>
- <version>2.0-SNAPSHOT</version>
+ <version>2.4-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
@@ -120,7 +120,7 @@
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer-tck</artifactId>
- <version>2.0-SNAPSHOT</version>
+ <version>2.4-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
Index: nanoextras/struts2/picocontainer-struts2/pom.xml
===================================================================
--- nanoextras/struts2/picocontainer-struts2/pom.xml (revision 4422)
+++ nanoextras/struts2/picocontainer-struts2/pom.xml (working copy)
@@ -17,7 +17,7 @@
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer</artifactId>
- <version>2.3-SNAPSHOT</version>
+ <version>2.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
Index: nanoextras/pom.xml
===================================================================
--- nanoextras/pom.xml (revision 4422)
+++ nanoextras/pom.xml (working copy)
@@ -8,10 +8,7 @@
<url>http://www.nanocontainer.org</url>
<modules>
- <module>nanosar</module>
<module>nanowar</module>
- <module>remoting</module>
- <module>persistence</module>
</modules>
<organization>
@@ -113,17 +110,17 @@
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer</artifactId>
- <version>2.0-SNAPSHOT</version>
+ <version>2.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer-gems</artifactId>
- <version>2.0-SNAPSHOT</version>
+ <version>2.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer-tck</artifactId>
- <version>2.0-SNAPSHOT</version>
+ <version>2.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>${pom.groupId}</groupId>
Index: pico/container/src/test/org/picocontainer/lifecycle/DefaultLifecycleStateTestCase.java
===================================================================
--- pico/container/src/test/org/picocontainer/lifecycle/DefaultLifecycleStateTestCase.java (revision 0)
+++ pico/container/src/test/org/picocontainer/lifecycle/DefaultLifecycleStateTestCase.java (revision 0)
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * Copyright (C) PicoContainer 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.picocontainer.lifecycle;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.picocontainer.lifecycle.DefaultLifecycleState.State.CONSTRUCTED;
+import static org.picocontainer.lifecycle.DefaultLifecycleState.State.DISPOSED;
+import static org.picocontainer.lifecycle.DefaultLifecycleState.State.STARTED;
+import static org.picocontainer.lifecycle.DefaultLifecycleState.State.STOPPED;
+
+import org.junit.Test;
+
+/**
+ * @author Michael Rimov
+ */
+public class DefaultLifecycleStateTestCase {
+
+ @Test public void testIsStartAllowedOptions() {
+ assertTrue(CONSTRUCTED.isStartAllowed());
+ assertFalse(STARTED.isStartAllowed());
+ assertTrue(STOPPED.isStartAllowed());
+ assertFalse(DISPOSED.isStartAllowed());
+ }
+
+ @Test public void testIsStopAllowedOptions() {
+ assertFalse(CONSTRUCTED.isStopAllowed());
+ assertTrue(STARTED.isStopAllowed());
+ assertFalse(STOPPED.isStopAllowed());
+ assertFalse(DISPOSED.isStopAllowed());
+ }
+
+ @Test public void testIsDisposeAllowedOptions() {
+ assertTrue(CONSTRUCTED.isDisposedAllowed());
+ assertFalse(STARTED.isDisposedAllowed());
+ assertTrue(STOPPED.isDisposedAllowed());
+ assertFalse(DISPOSED.isDisposedAllowed());
+ }
+
+}
Index: pico/container/src/test/org/picocontainer/lifecycle/LifecycleStateTestCase.java
===================================================================
--- pico/container/src/test/org/picocontainer/lifecycle/LifecycleStateTestCase.java (revision 4422)
+++ pico/container/src/test/org/picocontainer/lifecycle/LifecycleStateTestCase.java (working copy)
@@ -1,45 +0,0 @@
-/*****************************************************************************
- * Copyright (C) PicoContainer 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.picocontainer.lifecycle;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.picocontainer.lifecycle.LifecycleState.CONSTRUCTED;
-import static org.picocontainer.lifecycle.LifecycleState.DISPOSED;
-import static org.picocontainer.lifecycle.LifecycleState.STARTED;
-import static org.picocontainer.lifecycle.LifecycleState.STOPPED;
-
-import org.junit.Test;
-
-/**
- * @author Michael Rimov
- */
-public class LifecycleStateTestCase {
-
- @Test public void testIsStartAllowedOptions() {
- assertTrue(CONSTRUCTED.isStartAllowed());
- assertFalse(STARTED.isStartAllowed());
- assertTrue(STOPPED.isStartAllowed());
- assertFalse(DISPOSED.isStartAllowed());
- }
-
- @Test public void testIsStopAllowedOptions() {
- assertFalse(CONSTRUCTED.isStopAllowed());
- assertTrue(STARTED.isStopAllowed());
- assertFalse(STOPPED.isStopAllowed());
- assertFalse(DISPOSED.isStopAllowed());
- }
-
- @Test public void testIsDisposeAllowedOptions() {
- assertTrue(CONSTRUCTED.isDisposedAllowed());
- assertFalse(STARTED.isDisposedAllowed());
- assertTrue(STOPPED.isDisposedAllowed());
- assertFalse(DISPOSED.isDisposedAllowed());
- }
-
-}
Index: pico/container/src/java/org/picocontainer/lifecycle/LifecycleState.java
===================================================================
--- pico/container/src/java/org/picocontainer/lifecycle/LifecycleState.java (revision 4422)
+++ pico/container/src/java/org/picocontainer/lifecycle/LifecycleState.java (working copy)
@@ -12,72 +12,19 @@
* Current lifecycle state of the container.
* @author Michael Rimov
*/
-public enum LifecycleState {
+public interface LifecycleState {
- /**
- * Default state of a container once it has been built.
- */
- CONSTRUCTED,
-
- /**
- * 'Start' Lifecycle has been called.
- */
- STARTED,
-
- /**
- * 'Stop' lifecycle has been called.
- */
- STOPPED,
-
- /**
- * 'Dispose' lifecycle has been called.
- */
- DISPOSED;
-
-
- /**
- * Start is normally allowed if the object is constructed or
- * already stopped. It is not allowed if the system is already
- * started or disposed.
- * @return true if start lifecycle methods should be allowed.
- */
- public boolean isStartAllowed() {
- if (this.equals(CONSTRUCTED) || this.equals(STOPPED)) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Returns true if stop is normally allowed in the container
- * lifecycle. Stop is normally only allowed while the current
- * container state is STARTED.
- * @return true if stop is allowed.
- */
- public boolean isStopAllowed() {
- if (this.equals(STARTED)) {
- return true;
- }
-
- return false;
- }
-
- public boolean isStarted() {
- return this.equals(STARTED);
- }
-
- /**
- * Returns true if the dispose lifecycle method is normally called.
- * Dispose is normally only allowed if the object has not been already
- * disposed, and it is not started.
- * @return
- */
- public boolean isDisposedAllowed() {
- if (this.equals(STOPPED) || this.equals(CONSTRUCTED)) {
- return true;
- }
-
- return false;
- }
+ void removingComponent();
+
+ void starting();
+
+ void stopping();
+
+ void stopped();
+
+ boolean isStarted();
+
+ void disposing();
+
+ void disposed();
}
Index: pico/container/src/java/org/picocontainer/lifecycle/DefaultLifecycleState.java
===================================================================
--- pico/container/src/java/org/picocontainer/lifecycle/DefaultLifecycleState.java (revision 0)
+++ pico/container/src/java/org/picocontainer/lifecycle/DefaultLifecycleState.java (revision 0)
@@ -0,0 +1,125 @@
+package org.picocontainer.lifecycle;
+
+import org.picocontainer.PicoCompositionException;
+
+import java.io.Serializable;
+
+public class DefaultLifecycleState implements LifecycleState, Serializable {
+
+ private State state = State.CONSTRUCTED;
+
+ public void removingComponent() {
+ if (state == State.STARTED) {
+ throw new PicoCompositionException("Cannot remove components after the container has started");
+ }
+
+ if (state == State.DISPOSED) {
+ throw new PicoCompositionException("Cannot remove components after the container has been disposed");
+ }
+ }
+
+ public void starting() {
+ if (!state.isStartAllowed()) {
+ throw new IllegalStateException("Cannot start. Current container state was: " + state);
+ }
+
+ state = State.STARTED;
+
+ }
+
+ public void stopping() {
+ if (!state.isStopAllowed()) {
+ throw new IllegalStateException("Cannot stop. Current container state was: " + state);
+ }
+ }
+
+ public void stopped() {
+ state = State.STOPPED;
+ }
+
+ public boolean isStarted() {
+ return state == State.STARTED;
+ }
+
+ public void disposing() {
+ if (!state.isDisposedAllowed()) {
+ throw new IllegalStateException("Cannot dispose. Current lifecycle state is: " + state);
+ }
+
+ }
+
+ public void disposed() {
+ state = State.DISPOSED;
+ }
+
+ public enum State {
+
+ /**
+ * Default state of a container once it has been built.
+ */
+ CONSTRUCTED,
+
+ /**
+ * 'Start' Lifecycle has been called.
+ */
+ STARTED,
+
+ /**
+ * 'Stop' lifecycle has been called.
+ */
+ STOPPED,
+
+ /**
+ * 'Dispose' lifecycle has been called.
+ */
+ DISPOSED;
+
+
+ /**
+ * Start is normally allowed if the object is constructed or
+ * already stopped. It is not allowed if the system is already
+ * started or disposed.
+ * @return true if start lifecycle methods should be allowed.
+ */
+ public boolean isStartAllowed() {
+ if (this.equals(CONSTRUCTED) || this.equals(STOPPED)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if stop is normally allowed in the container
+ * lifecycle. Stop is normally only allowed while the current
+ * container state is STARTED.
+ * @return true if stop is allowed.
+ */
+ public boolean isStopAllowed() {
+ if (this.equals(STARTED)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public boolean isStarted() {
+ return this.equals(STARTED);
+ }
+
+ /**
+ * Returns true if the dispose lifecycle method is normally called.
+ * Dispose is normally only allowed if the object has not been already
+ * disposed, and it is not started.
+ * @return
+ */
+ public boolean isDisposedAllowed() {
+ if (this.equals(STOPPED) || this.equals(CONSTRUCTED)) {
+ return true;
+ }
+
+ return false;
+ }
+}
+
+}
Index: pico/container/src/java/org/picocontainer/DefaultPicoContainer.java
===================================================================
--- pico/container/src/java/org/picocontainer/DefaultPicoContainer.java (revision 4422)
+++ pico/container/src/java/org/picocontainer/DefaultPicoContainer.java (working copy)
@@ -20,8 +20,8 @@
import org.picocontainer.injectors.AbstractInjector;
import org.picocontainer.injectors.AdaptingInjection;
import org.picocontainer.lifecycle.LifecycleState;
-import static org.picocontainer.lifecycle.LifecycleState.*;
import org.picocontainer.lifecycle.StartableLifecycleStrategy;
+import org.picocontainer.lifecycle.DefaultLifecycleState;
import org.picocontainer.monitors.NullComponentMonitor;
import java.io.Serializable;
@@ -96,9 +96,9 @@
/**
* Current state of the container.
*/
- private LifecycleState lifecycleState = CONSTRUCTED;
-
- /**
+ private LifecycleState lifecycleState = new DefaultLifecycleState();
+
+ /**
* Keeps track of child containers started status.
*/
private final Set<WeakReference<PicoContainer>> childrenStarted = new HashSet<WeakReference<PicoContainer>>();
@@ -384,14 +384,8 @@
/** {@inheritDoc} **/
public <T> ComponentAdapter<T> removeComponent(final Object componentKey) {
- if (lifecycleState == STARTED) {
- throw new PicoCompositionException("Cannot remove components after the container has started");
- }
-
- if (lifecycleState == DISPOSED) {
- throw new PicoCompositionException("Cannot remove components after the container has been disposed");
- }
-
+ lifecycleState.removingComponent();
+
ComponentAdapter<T> adapter = (ComponentAdapter<T>) getComponentKeyToAdapterCache().remove(componentKey);
getModifiableComponentAdapterList().remove(adapter);
getOrderedComponentAdapters().remove(adapter);
@@ -632,12 +626,8 @@
* @see #removeChildContainer(PicoContainer)
*/
public void start() {
-
- if (!lifecycleState.isStartAllowed()) {
- throw new IllegalStateException("Cannot start. Current container state was: " + lifecycleState);
- }
- lifecycleState = STARTED;
+ lifecycleState.starting();
startAdapters();
childrenStarted.clear();
@@ -665,11 +655,10 @@
* @see #removeChildContainer(PicoContainer)
*/
public void stop() {
- if (!lifecycleState.isStopAllowed()) {
- throw new IllegalStateException("Cannot stop. Current container state was: " + lifecycleState);
- }
- for (PicoContainer child : children) {
+ lifecycleState.stopping();
+
+ for (PicoContainer child : children) {
if (childStarted(child)) {
if (child instanceof Startable) {
((Startable)child).stop();
@@ -677,7 +666,7 @@
}
}
stopAdapters();
- lifecycleState = STOPPED;
+ lifecycleState.stopped();
}
/**
@@ -719,20 +708,23 @@
if (lifecycleState.isStarted()) {
stop();
}
-
- if (!lifecycleState.isDisposedAllowed()) {
- throw new IllegalStateException("Cannot dispose. Current lifecycle state is: " + lifecycleState);
- }
+ lifecycleState.disposing();
+
for (PicoContainer child : children) {
if (child instanceof MutablePicoContainer) {
((Disposable)child).dispose();
}
}
disposeAdapters();
- lifecycleState = DISPOSED;
+
+ lifecycleState.disposed();
}
+ public void setLifecycleState(LifecycleState lifecycleState) {
+ this.lifecycleState = lifecycleState;
+ }
+
public MutablePicoContainer makeChildContainer() {
DefaultPicoContainer pc = new DefaultPicoContainer(componentFactory, lifecycleStrategy, this);
addChildContainer(pc);
@@ -775,7 +767,7 @@
checkCircularChildDependencies(child);
if (children.add(child)) {
// @todo Should only be added if child container has also be started
- if (lifecycleState == STARTED) {
+ if (lifecycleState.isStarted()) {
childrenStarted.add(new WeakReference<PicoContainer>(child));
}
}
Index: nano/pom.xml
===================================================================
--- nano/pom.xml (revision 4422)
+++ nano/pom.xml (working copy)
@@ -122,17 +122,17 @@
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer</artifactId>
- <version>2.3-SNAPSHOT</version>
+ <version>2.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer-gems</artifactId>
- <version>2.3-SNAPSHOT</version>
+ <version>2.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer-tck</artifactId>
- <version>2.3-SNAPSHOT</version>
+ <version>2.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>${pom.groupId}</groupId>