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.synchronization;
019    
020    import org.aopalliance.intercept.ConstructorInvocation;
021    import org.aopalliance.intercept.MethodInvocation;
022    import org.apache.log4j.Logger;
023    import org.objectweb.jac.core.AspectComponent;
024    import org.objectweb.jac.core.Interaction;
025    import org.objectweb.jac.core.Wrapper;
026    import org.objectweb.jac.util.Log;
027    import org.objectweb.jac.util.Semaphore;
028    
029    /**
030     * This aspect component allows the programmer to synchronize a set of
031     * methods on different objects or classes in a centralized way (do
032     * not use the synchronized java keyword anymore).
033     *
034     * <p>The monitor implementation to provide synchronization is
035     * implemented by a semaphore.
036     * 
037     * @see org.objectweb.jac.util.Semaphore */
038    
039    public class SynchronizationAC
040            extends AspectComponent
041            implements SynchronizationConf {
042    
043        static Logger logger = Logger.getLogger("synchronization");
044    
045            public void synchronize(String classes, String methods, String objects) {
046                    pointcut(
047                            objects,
048                            classes,
049                            methods,
050                            new SynchronizationWrapper(this),
051                            null);
052            }
053    
054            /**
055             * This inner wrapper implements the methods synchronization with a
056             * semaphore. */
057    
058            public class SynchronizationWrapper extends Wrapper {
059                    // one resource is available by default 
060                    // (only on thread can enter)
061                    Semaphore semaphore = new Semaphore(1);
062    
063                    public SynchronizationWrapper(AspectComponent ac) {
064                            super(ac);
065                    }
066    
067                    public Object synchronize(Interaction interaction) {
068                            Object ret = null;
069                            logger.debug(interaction.wrappee
070                             + " acquires semaphore for "
071                             + interaction.method);
072                            semaphore.acquire();
073                            try {
074                                    proceed(interaction);
075                            } finally {
076                                    logger.debug(interaction.wrappee
077                                 + " releases semaphore for "
078                                 + interaction.method);
079                                    semaphore.release();
080                            }
081                            return ret;
082                    }
083    
084                    public Object invoke(MethodInvocation invocation) throws Throwable {
085                            return synchronize((Interaction) invocation);
086                    }
087    
088                    public Object construct(ConstructorInvocation invocation)
089                            throws Throwable {
090                            return synchronize((Interaction) invocation);
091                    }
092    
093            }
094    }