001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.type.scope;
020
021import java.util.ArrayList;
022import java.util.Enumeration;
023import java.util.HashSet;
024import java.util.Iterator;
025import java.util.List;
026import java.util.Set;
027
028import javax.servlet.http.HttpSession;
029import javax.servlet.http.HttpSessionBindingEvent;
030import javax.servlet.http.HttpSessionBindingListener;
031
032import lucee.commons.lang.ExceptionUtil;
033import lucee.runtime.PageContext;
034import lucee.runtime.engine.ThreadLocalPageContext;
035import lucee.runtime.listener.ApplicationContext;
036import lucee.runtime.type.Collection;
037import lucee.runtime.type.scope.storage.MemoryScope;
038import lucee.runtime.type.util.KeyConstants;
039
040/**
041 * 
042 */
043public final class JSession extends ScopeSupport implements Session,HttpSessionBindingListener,MemoryScope {
044    
045        public static final Collection.Key SESSION_ID = KeyConstants._sessionid;
046        private static Set<Collection.Key> FIX_KEYS=new HashSet<Collection.Key>();
047        static {
048                FIX_KEYS.add(KeyConstants._sessionid);
049                FIX_KEYS.add(KeyConstants._urltoken);
050        }
051
052        
053        private String name;
054    private long timespan=-1;
055    private transient HttpSession httpSession;
056    private long lastAccess;
057        private long created;
058
059    /**
060     * constructor of the class
061     */
062    public JSession() {
063        super(true,"session",SCOPE_SESSION);
064        setDisplayName("Scope Session (Type JEE)");
065        this.created=System.currentTimeMillis();
066    }
067
068    @Override
069        public void touchBeforeRequest(PageContext pc) {
070                
071            ApplicationContext appContext = pc.getApplicationContext();
072            timespan=appContext.getSessionTimeout().getMillis();
073            this.name=appContext.getName();
074            HttpSession hs = pc.getSession();
075            String id="";
076            try{
077                    if(hs!=null)this.httpSession=hs;
078                    if(httpSession!=null) {
079                            id = httpSession.getId();
080                            int timeoutInSeconds = ((int)(timespan/1000))+60;
081                            if(httpSession.getMaxInactiveInterval()<timeoutInSeconds)
082                                httpSession.setMaxInactiveInterval(timeoutInSeconds);
083                    }
084                    
085                }
086            catch(Throwable t) {
087                        ExceptionUtil.rethrowIfNecessary(t);
088                
089            }
090         
091
092            lastAccess=System.currentTimeMillis();
093        setEL(KeyConstants._sessionid,id);
094        setEL(KeyConstants._urltoken,"CFID="+pc.getCFID()+"&CFTOKEN="+pc.getCFToken()+"&jsessionid="+id);
095        }
096
097        public void touchAfterRequest(PageContext pc) {
098                
099        }
100        @Override
101        public void release() {
102                release(ThreadLocalPageContext.get());
103        }
104        
105        @Override
106        public void release(PageContext pc) {
107        if(httpSession!=null){
108                try {
109                        Object key;
110                        Enumeration e = httpSession.getAttributeNames();
111                        while(e.hasMoreElements()) {
112                                // TODO set inative time new
113                                key=e.nextElement();
114                                if(key.equals(name))httpSession.removeAttribute(name);
115                        }
116                        name=null;
117                        timespan=-1;
118                        httpSession=null;
119                        lastAccess=-1;
120                }
121                catch(Throwable t) {
122                                ExceptionUtil.rethrowIfNecessary(t);
123                        }
124        }
125        super.release(pc);
126    }
127
128    @Override
129    public long getLastAccess() {
130        return lastAccess;
131    }
132
133    @Override
134    public long getTimeSpan() {
135        return timespan;
136    }
137
138    @Override
139    public boolean isExpired() {
140        return (getLastAccess()+getTimeSpan())<System.currentTimeMillis();
141    }
142
143    @Override
144    public void valueBound(HttpSessionBindingEvent event) {
145        
146    }
147
148    @Override
149    public void valueUnbound(HttpSessionBindingEvent event) {
150        clear();
151    }
152        
153    @Override
154    public void touch() {
155                lastAccess=System.currentTimeMillis();
156        }
157
158        @Override
159        public long getCreated() {
160                return created;
161        }
162        
163        public Collection.Key[] pureKeys() {
164                List<Collection.Key> keys=new ArrayList<Collection.Key>();
165                Iterator<Key> it = keyIterator();
166                Collection.Key key;
167                while(it.hasNext()){
168                        key=it.next();
169                        if(!FIX_KEYS.contains(key))keys.add(key);
170                }
171                return keys.toArray(new Collection.Key[keys.size()]);
172        }
173
174        @Override
175        public void resetEnv(PageContext pc) {
176                created=System.currentTimeMillis();
177                lastAccess=System.currentTimeMillis();
178                touchBeforeRequest(pc);
179        }
180}