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