001    /*
002      Copyright (C) 2001 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.distribution.consistency;
019    
020    import java.util.*;
021    import org.apache.log4j.Logger;
022    import org.objectweb.jac.core.*;
023    import org.objectweb.jac.core.dist.*;
024    import org.objectweb.jac.core.rtti.ClassRepository;
025    import org.objectweb.jac.util.*;
026    
027    /**
028     * This wrapper implements a client-server consistency protocol.
029     *
030     * <p>It is a special consistency protocol since the wrappee acts as a
031     * pure client (a stub) for its known replicas.<p>
032     * 
033     * @author <a href="http://cedric.cnam.fr/~pawlak/index-english.html">Renaud Pawlak</a> */
034    
035    public class ClientServerConsistencyWrapper extends ConsistencyWrapper {
036        static Logger logger = Logger.getLogger("consistency");
037    
038        String hosts = null;
039    
040        /**
041        * A friendly constructor for a client-server consistency wrapper.
042        *
043        * @param hosts a regular expression that defines the host where
044        * the server is located 
045        */
046        public ClientServerConsistencyWrapper(AspectComponent ac, String hosts) {
047            super(ac);
048            knownReplicas = null;
049            this.hosts = hosts;
050        } 
051    
052        /** An empty constructor for the Consistency class. */
053        public ClientServerConsistencyWrapper(AspectComponent ac) {
054            super(ac);
055        }
056    
057        /**
058        * Forwards the call to the server(s).<p>
059        *
060        * Do not call the replica except if we do not know any server (in
061        * this case, we are a server).<p>
062        *
063        * @return the value returned by the server */
064    
065        public Object whenCall(Interaction interaction) {
066    
067            if( knownReplicas == null ) {
068                knownReplicas = Topology.getPartialTopology(hosts).getReplicas(interaction.wrappee);
069            } 
070    
071            if(knownReplicas != null && knownReplicas.size() > 0 &&
072               (! ((RemoteRef)knownReplicas.get(0)).getRemCont().isLocal()) ) {
073                logger.debug("(client-server) call event on " + 
074                          NameRepository.get().getName(interaction.wrappee) + 
075                          ":" + interaction.method + ":" + 
076                          ((RemoteRef)knownReplicas.get(0)).getRemCont().getName());
077                Object ret = ((RemoteRef)knownReplicas.get(0)).invokeRoleMethod(
078                    "acceptRemoteCall",
079                    new Object[] { null, new Object[] { interaction.method, interaction.args } }
080                );
081                return ret;
082            } else {
083                /* we do not know any replica, so we are the server... */
084                return proceed(interaction);
085            }
086        }
087    
088        /**
089        * Calls the method on the server.
090        *
091        * @param remoteReplica the client remote reference
092        * @param data the name and the parameters of the server method
093        */
094    
095        public Object acceptRemoteCall(Wrappee wrappee, RemoteRef remoteReplica,
096                                       Object[] data) {
097            logger.debug("(client-server) remote call event on " + 
098                         NameRepository.get().getName(wrappee) +
099                         ":" + (String)data[0] + ":" + 
100                         Arrays.asList((Object[])data[1]));
101            return ClassRepository.get().getClass(wrappee).getMethod((String)data[0]).invoke(
102                wrappee , (Object[])data[1] );
103        }
104    }