001 /* 002 Copyright (C) 2001-2002 Renaud Pawlak <renaud@aopsys.com> 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public License 015 along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 017 018 package org.objectweb.jac.aspects.session; 019 020 import java.util.*; 021 import org.aopalliance.intercept.ConstructorInvocation; 022 import org.aopalliance.intercept.MethodInvocation; 023 import org.apache.log4j.Logger; 024 import org.objectweb.jac.core.*; 025 import org.objectweb.jac.util.*; 026 027 /** 028 * This wrapper handles per-session objects within the JAC system. 029 * 030 * <p>For each session, it uses a different copy of the original 031 * object so that each client see a different state. 032 * 033 * @see #handlePerSessionObject(Interaction) 034 * @author Renaud Pawlak */ 035 036 public class PerSessionObjectWrapper extends Wrapper { 037 static Logger logger = Logger.getLogger("session"); 038 039 Hashtable sessionObjects = new Hashtable(); 040 041 public PerSessionObjectWrapper(AspectComponent ac) { 042 super(ac); 043 } 044 045 /** 046 * This wrapping method handles an hashtable of copied objects. 047 * 048 * <p>There is one copied object per session with possibly a 049 * different state from the original. The call is thus forwarded to 050 * the copy that corresponds to the session. 051 * 052 * <p>The first time, the original object is cloned so that its 053 * state is that same as the original. 054 * 055 * @return the result given by the per-session copy */ 056 057 public Object handlePerSessionObject(Interaction interaction) { 058 059 logger.debug("handling per-session object for " + interaction.wrappee); 060 061 String sid = (String) attr( "Session.sid" ); 062 063 if ( sid == null || sid.startsWith("Swing") ) { 064 logger.debug("session is not defined by client"); 065 return proceed(interaction); 066 } 067 068 logger.debug("found session " + sid); 069 070 Object sessionObject = null; 071 072 if ( sessionObjects.containsKey( sid ) ) { 073 sessionObject = sessionObjects.get( sid ); 074 } else { 075 // the initial session object has the same state as the original 076 // object 077 logger.debug("cloning object " + interaction.wrappee); 078 sessionObject = Wrapping.clone(interaction.wrappee); 079 sessionObjects.put(sid,sessionObject); 080 } 081 082 Object result = null; 083 if( sessionObject == interaction.wrappee ) { 084 // we are the session object, this should not happend if 085 // the session aspect is correctly defined 086 logger.warn(interaction.wrappee+ 087 " is a session object and is wrapped."); 088 result = proceed(interaction); 089 } else { 090 // we forward the call to the session object 091 // (and we do not use the original) 092 logger.debug(interaction.wrappee+" forwarding to session object " + 093 sessionObject+"."+interaction.method); 094 result = interaction.invoke(sessionObject); 095 } 096 return result; 097 } 098 099 public Object invoke(MethodInvocation invocation) throws Throwable { 100 return handlePerSessionObject((Interaction) invocation); 101 } 102 103 public Object construct(ConstructorInvocation invocation) 104 throws Throwable { 105 throw new Exception("Wrapper "+this+" does not support construction interception."); 106 } 107 108 }