001/*
002 * Copyright 2002-2012 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.context.request;
018
019import org.springframework.beans.factory.ObjectFactory;
020
021/**
022 * Session-backed {@link org.springframework.beans.factory.config.Scope}
023 * implementation.
024 *
025 * <p>Relies on a thread-bound {@link RequestAttributes} instance, which
026 * can be exported through {@link RequestContextListener},
027 * {@link org.springframework.web.filter.RequestContextFilter} or
028 * {@link org.springframework.web.servlet.DispatcherServlet}.
029 *
030 * <p>This {@code Scope} will also work for Portlet environments,
031 * through an alternate {@code RequestAttributes} implementation
032 * (as exposed out-of-the-box by Spring's
033 * {@link org.springframework.web.portlet.DispatcherPortlet}.
034 *
035 * @author Rod Johnson
036 * @author Juergen Hoeller
037 * @author Rob Harrop
038 * @since 2.0
039 * @see RequestContextHolder#currentRequestAttributes()
040 * @see RequestAttributes#SCOPE_SESSION
041 * @see RequestAttributes#SCOPE_GLOBAL_SESSION
042 * @see RequestContextListener
043 * @see org.springframework.web.filter.RequestContextFilter
044 * @see org.springframework.web.servlet.DispatcherServlet
045 * @see org.springframework.web.portlet.DispatcherPortlet
046 */
047public class SessionScope extends AbstractRequestAttributesScope {
048
049        private final int scope;
050
051
052        /**
053         * Create a new SessionScope, storing attributes in a locally
054         * isolated session (or default session, if there is no distinction
055         * between a global session and a component-specific session).
056         */
057        public SessionScope() {
058                this.scope = RequestAttributes.SCOPE_SESSION;
059        }
060
061        /**
062         * Create a new SessionScope, specifying whether to store attributes
063         * in the global session, provided that such a distinction is available.
064         * <p>This distinction is important for Portlet environments, where there
065         * are two notions of a session: "portlet scope" and "application scope".
066         * If this flag is on, objects will be put into the "application scope" session;
067         * else they will end up in the "portlet scope" session (the typical default).
068         * <p>In a Servlet environment, this flag is effectively ignored.
069         * @param globalSession {@code true} in case of the global session as target;
070         * {@code false} in case of a component-specific session as target
071         * @see org.springframework.web.portlet.context.PortletRequestAttributes
072         * @see ServletRequestAttributes
073         */
074        public SessionScope(boolean globalSession) {
075                this.scope = (globalSession ? RequestAttributes.SCOPE_GLOBAL_SESSION : RequestAttributes.SCOPE_SESSION);
076        }
077
078
079        @Override
080        protected int getScope() {
081                return this.scope;
082        }
083
084        @Override
085        public String getConversationId() {
086                return RequestContextHolder.currentRequestAttributes().getSessionId();
087        }
088
089        @Override
090        public Object get(String name, ObjectFactory<?> objectFactory) {
091                Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex();
092                synchronized (mutex) {
093                        return super.get(name, objectFactory);
094                }
095        }
096
097        @Override
098        public Object remove(String name) {
099                Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex();
100                synchronized (mutex) {
101                        return super.remove(name);
102                }
103        }
104
105}