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    }