001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    package org.apache.shiro.session.mgt;
020    
021    import org.apache.shiro.session.InvalidSessionException;
022    import org.apache.shiro.session.Session;
023    
024    import java.io.Serializable;
025    import java.util.Collection;
026    import java.util.Date;
027    
028    /**
029     * A DelegatingSession is a client-tier representation of a server side
030     * {@link org.apache.shiro.session.Session Session}.
031     * This implementation is basically a proxy to a server-side {@link NativeSessionManager NativeSessionManager},
032     * which will return the proper results for each method call.
033     * <p/>
034     * <p>A <tt>DelegatingSession</tt> will cache data when appropriate to avoid a remote method invocation,
035     * only communicating with the server when necessary.
036     * <p/>
037     * <p>Of course, if used in-process with a NativeSessionManager business POJO, as might be the case in a
038     * web-based application where the web classes and server-side business pojos exist in the same
039     * JVM, a remote method call will not be incurred.
040     *
041     * @author Les Hazlewood
042     * @author Jeremy Haile
043     * @since 0.1
044     */
045    public class DelegatingSession implements Session, Serializable {
046    
047        //TODO - complete JavaDoc
048    
049        private final SessionKey key;
050    
051        //cached fields to avoid a server-side method call if out-of-process:
052        private Date startTimestamp = null;
053        private String host = null;
054    
055        /**
056         * Handle to the target NativeSessionManager that will support the delegate calls.
057         */
058        private final transient NativeSessionManager sessionManager;
059    
060    
061        public DelegatingSession(NativeSessionManager sessionManager, SessionKey key) {
062            if (sessionManager == null) {
063                throw new IllegalArgumentException("sessionManager argument cannot be null.");
064            }
065            if (key == null) {
066                throw new IllegalArgumentException("sessionKey argument cannot be null.");
067            }
068            if (key.getSessionId() == null) {
069                String msg = "The " + DelegatingSession.class.getName() + " implementation requires that the " +
070                        "SessionKey argument returns a non-null sessionId to support the " +
071                        "Session.getId() invocations.";
072                throw new IllegalArgumentException(msg);
073            }
074            this.sessionManager = sessionManager;
075            this.key = key;
076        }
077    
078        /**
079         * @see org.apache.shiro.session.Session#getId()
080         */
081        public Serializable getId() {
082            return key.getSessionId();
083        }
084    
085        /**
086         * @see org.apache.shiro.session.Session#getStartTimestamp()
087         */
088        public Date getStartTimestamp() {
089            if (startTimestamp == null) {
090                startTimestamp = sessionManager.getStartTimestamp(key);
091            }
092            return startTimestamp;
093        }
094    
095        /**
096         * @see org.apache.shiro.session.Session#getLastAccessTime()
097         */
098        public Date getLastAccessTime() {
099            //can't cache - only business pojo knows the accurate time:
100            return sessionManager.getLastAccessTime(key);
101        }
102    
103        public long getTimeout() throws InvalidSessionException {
104            return sessionManager.getTimeout(key);
105        }
106    
107        public void setTimeout(long maxIdleTimeInMillis) throws InvalidSessionException {
108            sessionManager.setTimeout(key, maxIdleTimeInMillis);
109        }
110    
111        public String getHost() {
112            if (host == null) {
113                host = sessionManager.getHost(key);
114            }
115            return host;
116        }
117    
118        /**
119         * @see org.apache.shiro.session.Session#touch()
120         */
121        public void touch() throws InvalidSessionException {
122            sessionManager.touch(key);
123        }
124    
125        /**
126         * @see org.apache.shiro.session.Session#stop()
127         */
128        public void stop() throws InvalidSessionException {
129            sessionManager.stop(key);
130        }
131    
132        /**
133         * @see org.apache.shiro.session.Session#getAttributeKeys
134         */
135        public Collection<Object> getAttributeKeys() throws InvalidSessionException {
136            return sessionManager.getAttributeKeys(key);
137        }
138    
139        /**
140         * @see org.apache.shiro.session.Session#getAttribute(Object key)
141         */
142        public Object getAttribute(Object attributeKey) throws InvalidSessionException {
143            return sessionManager.getAttribute(this.key, attributeKey);
144        }
145    
146        /**
147         * @see Session#setAttribute(Object key, Object value)
148         */
149        public void setAttribute(Object attributeKey, Object value) throws InvalidSessionException {
150            if (value == null) {
151                removeAttribute(attributeKey);
152            } else {
153                sessionManager.setAttribute(this.key, attributeKey, value);
154            }
155        }
156    
157        /**
158         * @see Session#removeAttribute(Object key)
159         */
160        public Object removeAttribute(Object attributeKey) throws InvalidSessionException {
161            return sessionManager.removeAttribute(this.key, attributeKey);
162        }
163    }