001    /*
002      Copyright (C) 2002 Laurent Martelli <laurent@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.cache;
019    
020    import java.util.Hashtable;
021    import org.aopalliance.intercept.ConstructorInvocation;
022    import org.aopalliance.intercept.MethodInvocation;
023    import org.apache.log4j.Logger;
024    import org.objectweb.jac.aspects.timestamp.Timestamps;
025    import org.objectweb.jac.core.AspectComponent;
026    import org.objectweb.jac.core.Interaction;
027    import org.objectweb.jac.core.NameRepository;
028    import org.objectweb.jac.core.Wrapper;
029    import org.objectweb.jac.util.ObjectArray;
030    
031    /**
032     * The wrapper of the CacheAC.
033     * @see CacheAC
034     */
035    public class CacheWrapper extends Wrapper {
036        static final Logger logger = Logger.getLogger("cache");
037    
038        public CacheWrapper(AspectComponent ac) {
039            super(ac);
040        }
041    
042        public CacheWrapper(AspectComponent ac, String stampsName) {
043            super(ac);
044            this.stampsName = stampsName;
045        }
046    
047        String stampsName;
048        Timestamps stamps;
049    
050        public Object invoke(MethodInvocation invocation) throws Throwable {
051                    return cache((Interaction)invocation);
052        }
053    
054        public Object construct(ConstructorInvocation invocation) throws Throwable {
055                    throw new Exception("This wrapper does not support constructor wrapping");
056        }
057       
058        Hashtable cache = new Hashtable();
059       
060        public Object cache(Interaction interaction) {
061            logger.debug("cache "+interaction+"?");
062            // Synchronization is not crucial: we may only loose cached value
063            MethodCache methodCache = (MethodCache)cache.get(interaction.method);
064            if (methodCache==null) {
065                if (stampsName!=null) {
066                    if (stamps == null)
067                        stamps = (Timestamps)NameRepository.get().getObject(stampsName);
068                }
069                methodCache = new MethodCache(stamps);
070                cache.put(interaction.method,methodCache);
071            }
072            Object[] argsArray = new Object[interaction.args.length];
073            System.arraycopy(interaction.args, 0, argsArray, 0, interaction.args.length);
074            int[] ignoredArgs = (int[])interaction.method.getAttribute(CacheAC.IGNORED_PARAMETERS);
075            ObjectArray args = new ObjectArray(argsArray);
076    
077            MethodCache.Entry entry = methodCache.getEntry(args,ignoredArgs);
078            if (entry!=null) {
079                return entry.value;
080            }
081            Object result = proceed(interaction);
082            methodCache.putEntry(args,result);
083            return result;
084        }
085    
086        /**
087         * Invalidates the cache 
088         */
089        void invalidate() {
090            cache.clear();
091        }
092    
093    }