001// Copyright 2006-2013 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.http.internal.services; 016 017import java.util.Collections; 018import java.util.Enumeration; 019import java.util.List; 020import java.util.Objects; 021 022import org.apache.tapestry5.commons.util.CollectionFactory; 023import org.apache.tapestry5.http.services.Session; 024import org.apache.tapestry5.ioc.internal.util.InternalUtils; 025 026import javax.servlet.http.HttpServletRequest; 027import javax.servlet.http.HttpSession; 028 029/** 030 * A thin wrapper around {@link HttpSession}. 031 */ 032public class SessionImpl implements Session 033{ 034 private final HttpServletRequest request; 035 036 private final HttpSession session; 037 038 private boolean invalidated = false; 039 040 private final SessionLock lock; 041 042 public SessionImpl(HttpServletRequest request, HttpSession session, SessionLock lock) 043 { 044 this.request = request; 045 this.session = session; 046 this.lock = lock; 047 } 048 049 @Override 050 public Object getAttribute(String name) 051 { 052 return getAttribute(name, Session.LockMode.WRITE); 053 } 054 055 @Override 056 public Object getAttribute(String name, Session.LockMode lockMode) 057 { 058 Objects.requireNonNull(name, "name must be non-null"); 059 060 // If a WRITE lock is requested, check first if the key exists 061 // to prevent a lock upgrade if not necessary. 062 if (lockMode == null || lockMode == Session.LockMode.WRITE) 063 { 064 if (!containsAttribute(name)) return null; 065 } 066 067 acquireLock(lockMode, Session.LockMode.WRITE); 068 069 return session.getAttribute(name); 070 } 071 072 @Override 073 public List<String> getAttributeNames() 074 { 075 return getAttributeNames(Session.LockMode.READ); 076 } 077 078 @Override 079 public List<String> getAttributeNames(Session.LockMode lockMode) 080 { 081 acquireLock(lockMode, Session.LockMode.READ); 082 083 return InternalUtils.toList(session.getAttributeNames()); 084 } 085 086 @Override 087 public void setAttribute(String name, Object value) 088 { 089 Objects.requireNonNull(name, "name must be non-null"); 090 091 lock.acquireWriteLock(); 092 093 session.setAttribute(name, value); 094 } 095 096 @Override 097 public boolean containsAttribute(String name) 098 { 099 return containsAttribute(name, Session.LockMode.READ); 100 } 101 102 @Override 103 public boolean containsAttribute(String name, Session.LockMode lockMode) 104 { 105 Objects.requireNonNull(name, "name must be non-null"); 106 107 acquireLock(lockMode, Session.LockMode.READ); 108 109 Enumeration<String> e = session.getAttributeNames(); 110 while (e.hasMoreElements()) 111 { 112 String attrName = e.nextElement(); 113 if (attrName.equals(name)) return true; 114 } 115 116 return false; 117 } 118 119 @Override 120 public List<String> getAttributeNames(String prefix) 121 { 122 return getAttributeNames(prefix, Session.LockMode.READ); 123 } 124 125 @Override 126 public List<String> getAttributeNames(String prefix, Session.LockMode lockMode) 127 { 128 Objects.requireNonNull(prefix, "prefix must be non-null"); 129 130 acquireLock(lockMode, Session.LockMode.READ); 131 132 List<String> result = CollectionFactory.newList(); 133 134 Enumeration<String> e = session.getAttributeNames(); 135 while (e.hasMoreElements()) 136 { 137 String name = e.nextElement(); 138 139 if (name.startsWith(prefix)) result.add(name); 140 } 141 142 Collections.sort(result); 143 144 return result; 145 } 146 147 @Override 148 public int getMaxInactiveInterval() 149 { 150 return session.getMaxInactiveInterval(); 151 } 152 153 @Override 154 public void invalidate() 155 { 156 invalidated = true; 157 158 session.invalidate(); 159 } 160 161 @Override 162 public boolean isInvalidated() 163 { 164 if (invalidated) return true; 165 166 // The easy case is when the session was invalidated through the Tapestry Session 167 // object. The hard case is when the HttpSession was invalidated outside of Tapestry, 168 // in which case, request.getSession() will return a new HttpSession instance (or null) 169 170 invalidated = request.getSession(false) != session; 171 172 return invalidated; 173 } 174 175 @Override 176 public void setMaxInactiveInterval(int seconds) 177 { 178 session.setMaxInactiveInterval(seconds); 179 } 180 181 @Override 182 public void restoreDirtyObjects() 183 { 184 185 } 186 187 private void acquireLock(Session.LockMode requestedMode, Session.LockMode defaultMode) { 188 if (requestedMode == null) 189 { 190 requestedMode = defaultMode; 191 } 192 193 switch (requestedMode) 194 { 195 case NONE: 196 break; 197 case READ: 198 this.lock.acquireReadLock(); 199 break; 200 case WRITE: 201 this.lock.acquireWriteLock(); 202 break; 203 } 204 } 205}