001// Copyright 2011, 2013, 2020 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 org.apache.tapestry5.commons.util.CollectionFactory; 018import org.apache.tapestry5.http.services.SessionPersistedObjectAnalyzer; 019import org.apache.tapestry5.ioc.services.PerthreadManager; 020 021import javax.servlet.http.HttpServletRequest; 022import javax.servlet.http.HttpSession; 023import java.util.Map; 024 025/** 026 * A thin wrapper around {@link javax.servlet.http.HttpSession} that supports re-storing of mutable 027 * session attributes at the end of the request (see {@link #restoreDirtyObjects()}). This is only 028 * used when {@linkplain org.apache.tapestry5.SymbolConstants#CLUSTERED_SESSIONS clustering}. 029 * 030 * @since 5.3 031 * @see SessionPersistedObjectAnalyzer 032 */ 033public class ClusteredSessionImpl extends SessionImpl 034{ 035 private final SessionPersistedObjectAnalyzer analyzer; 036 037 /** 038 * Cache of attribute objects read from, or written to, the real session. 039 * This is needed for end-of-request 040 * processing. 041 */ 042 private final Map<String, Object> sessionAttributeCache = CollectionFactory.newMap(); 043 044 public ClusteredSessionImpl(HttpServletRequest request, 045 HttpSession session, 046 SessionLock lock, SessionPersistedObjectAnalyzer analyzer) 047 { 048 super(request, session, lock); 049 050 this.analyzer = analyzer; 051 } 052 053 @Override 054 public Object getAttribute(String name) 055 { 056 Object result = super.getAttribute(name); 057 058 sessionAttributeCache.put(name, result); 059 060 return result; 061 } 062 063 public void setAttribute(String name, Object value) 064 { 065 super.setAttribute(name, value); 066 067 sessionAttributeCache.put(name, value); 068 } 069 070 public void invalidate() 071 { 072 super.invalidate(); 073 074 sessionAttributeCache.clear(); 075 } 076 077 public void restoreDirtyObjects() 078 { 079 if (isInvalidated()) 080 { 081 return; 082 } 083 084 if (sessionAttributeCache.isEmpty()) 085 { 086 return; 087 } 088 089 for (Map.Entry<String, Object> entry : sessionAttributeCache.entrySet()) 090 { 091 String attributeName = entry.getKey(); 092 093 Object attributeValue = entry.getValue(); 094 095 if (attributeValue == null) 096 { 097 continue; 098 } 099 100 if (analyzer.checkAndResetDirtyState(attributeValue)) 101 { 102 super.setAttribute(attributeName, attributeValue); 103 } 104 } 105 } 106}