001/*
002 * Copyright 2002-2017 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.messaging.simp;
018
019import org.springframework.beans.factory.ObjectFactory;
020import org.springframework.beans.factory.config.Scope;
021import org.springframework.lang.Nullable;
022
023/**
024 * A {@link Scope} implementation exposing the attributes of a SiMP session
025 * (e.g. WebSocket session).
026 *
027 * <p>Relies on a thread-bound {@link SimpAttributes} instance exported by
028 * {@link org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler}.
029 *
030 * @author Rossen Stoyanchev
031 * @since 4.1
032 */
033public class SimpSessionScope implements Scope {
034
035        @Override
036        public Object get(String name, ObjectFactory<?> objectFactory) {
037                SimpAttributes simpAttributes = SimpAttributesContextHolder.currentAttributes();
038                Object scopedObject = simpAttributes.getAttribute(name);
039                if (scopedObject != null) {
040                        return scopedObject;
041                }
042                synchronized (simpAttributes.getSessionMutex()) {
043                        scopedObject = simpAttributes.getAttribute(name);
044                        if (scopedObject == null) {
045                                scopedObject = objectFactory.getObject();
046                                simpAttributes.setAttribute(name, scopedObject);
047                        }
048                        return scopedObject;
049                }
050        }
051
052        @Override
053        @Nullable
054        public Object remove(String name) {
055                SimpAttributes simpAttributes = SimpAttributesContextHolder.currentAttributes();
056                synchronized (simpAttributes.getSessionMutex()) {
057                        Object value = simpAttributes.getAttribute(name);
058                        if (value != null) {
059                                simpAttributes.removeAttribute(name);
060                                return value;
061                        }
062                        else {
063                                return null;
064                        }
065                }
066        }
067
068        @Override
069        public void registerDestructionCallback(String name, Runnable callback) {
070                SimpAttributesContextHolder.currentAttributes().registerDestructionCallback(name, callback);
071        }
072
073        @Override
074        @Nullable
075        public Object resolveContextualObject(String key) {
076                return null;
077        }
078
079        @Override
080        public String getConversationId() {
081                return SimpAttributesContextHolder.currentAttributes().getSessionId();
082        }
083
084}