001    package org.picocontainer.web;
002    
003    import java.io.IOException;
004    import java.io.Serializable;
005    
006    import javax.servlet.Filter;
007    import javax.servlet.FilterChain;
008    import javax.servlet.FilterConfig;
009    import javax.servlet.ServletContext;
010    import javax.servlet.ServletException;
011    import javax.servlet.ServletRequest;
012    import javax.servlet.ServletResponse;
013    import javax.servlet.http.HttpServletRequest;
014    import javax.servlet.http.HttpSession;
015    
016    import org.picocontainer.DefaultPicoContainer;
017    import org.picocontainer.MutablePicoContainer;
018    import org.picocontainer.behaviors.Storing;
019    
020    @SuppressWarnings("serial")
021    public abstract class PicoServletContainerFilter implements Filter, Serializable {
022    
023        public void init(FilterConfig filterConfig) throws ServletException {
024            ServletContext servletContext = filterConfig.getServletContext();
025            ApplicationContainerHolder ach = (ApplicationContainerHolder) servletContext
026                    .getAttribute(ApplicationContainerHolder.class.getName());
027            setAppContainer(ach.getContainer());
028        }
029    
030        public void destroy() {
031        }
032    
033        public static Object getRequestComponentForThread(Class<?> type) {
034            MutablePicoContainer requestContainer = ServletFilter.getRequestContainerForThread();
035            MutablePicoContainer container = new DefaultPicoContainer(requestContainer);
036            container.addComponent(type);
037            return container.getComponent(type);
038        }
039    
040        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException,
041                ServletException {
042    
043            HttpServletRequest httpReq = (HttpServletRequest) req;
044            HttpSession session = httpReq.getSession();
045            ServletContext context = session.getServletContext();
046    
047            ApplicationContainerHolder ach = (ApplicationContainerHolder) context
048                    .getAttribute(ApplicationContainerHolder.class.getName());
049            SessionContainerHolder sch = (SessionContainerHolder) context.getAttribute(SessionContainerHolder.class
050                    .getName());
051            RequestContainerHolder rch = (RequestContainerHolder) context.getAttribute(RequestContainerHolder.class
052                    .getName());
053    
054            Storing sessionStoring = sch.getStoring();
055            Storing requestStoring = rch.getStoring();
056    
057            SessionStoreHolder ssh = (SessionStoreHolder) session.getAttribute(SessionStoreHolder.class.getName());
058            sessionStoring.putCacheForThread(ssh.getStoreWrapper());
059            requestStoring.resetCacheForThread();
060            rch.getLifecycleStateModel().resetStateModelForThread();
061            rch.getContainer().start();
062    
063            setAppContainer(ach.getContainer());
064            setSessionContainer(sch.getContainer());
065            setRequestContainer(rch.getContainer());
066    
067            filterChain.doFilter(req, resp);
068    
069            setAppContainer(null);
070            setSessionContainer(null);
071            setRequestContainer(null);
072    
073            rch.getContainer().stop();
074            rch.getContainer().dispose();
075            rch.getLifecycleStateModel().invalidateStateModelForThread();
076            sessionStoring.invalidateCacheForThread();
077            requestStoring.invalidateCacheForThread();
078    
079        }
080    
081        protected abstract void setAppContainer(MutablePicoContainer container);
082    
083        protected abstract void setSessionContainer(MutablePicoContainer container);
084    
085        protected abstract void setRequestContainer(MutablePicoContainer container);
086    
087        public static class ServletFilter extends PicoServletContainerFilter {
088    
089            private static ThreadLocal<MutablePicoContainer> currentRequestContainer = new ThreadLocal<MutablePicoContainer>();
090            private static ThreadLocal<MutablePicoContainer> currentSessionContainer = new ThreadLocal<MutablePicoContainer>();
091            private static ThreadLocal<MutablePicoContainer> currentAppContainer = new ThreadLocal<MutablePicoContainer>();
092    
093            protected void setAppContainer(MutablePicoContainer container) {
094                currentAppContainer.set(container);
095            }
096    
097            protected void setRequestContainer(MutablePicoContainer container) {
098                currentRequestContainer.set(container);
099            }
100    
101            protected void setSessionContainer(MutablePicoContainer container) {
102                currentSessionContainer.set(container);
103            }
104    
105            public static MutablePicoContainer getRequestContainerForThread() {
106                return currentRequestContainer.get();
107            }
108    
109            public static MutablePicoContainer getSessionContainerForThread() {
110                return currentSessionContainer.get();
111            }
112    
113            public static MutablePicoContainer getApplicationContainerForThread() {
114                return currentAppContainer.get();
115            }
116        }
117    }