001    /*
002    
003      Copyright (C) 2001 Lionel Seinturier
004    
005      This program is free software; you can redistribute it and/or modify
006      it under the terms of the Lesser GNU Lesser General Public License as
007      published by the Free Software Foundation; either version 2 of the
008      License, or (at your option) any later version.
009    
010      This program is distributed in the hope that it will be useful,
011      but WITHOUT ANY WARRANTY; without even the implied warranty of
012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013      GNU Lesser General Public License for more details.
014    
015      You should have received a copy of the GNU Lesser Generaly Public License
016      along with this program; if not, write to the Free Software
017      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
018    
019    package org.objectweb.jac.core.dist;
020    
021    import org.apache.log4j.Logger;
022    import org.objectweb.jac.core.*;
023    import org.objectweb.jac.util.*;
024    
025    /**
026     * NonBlockingStubWrapper is a dynamic client stub for org.objectweb.jac.
027     * Every method called on an object wrapped by such a wrapper
028     * is forwarded to a remote reference.
029     *
030     * The call is non blocking.
031     * For blocking calls see StubWrapper.
032     *
033     * This a wrapper class.
034     * The invoke method wraps all the methods of a wrappee.
035     *
036     * @see org.objectweb.jac.core.dist.StubWrapper
037     *
038     * @author <a href="http://www-src.lip6.fr/homepages/Lionel.Seinturier/index-eng.html">Lionel Seinturier</a>
039     */
040     
041    public class NonBlockingStubWrapper extends StubWrapper {
042        static Logger logger = Logger.getLogger("stub");
043    
044       /**
045        * Construct a new dynamic stub.
046        *
047        * @param remoteRef  the remote reference associated to the stub
048        */
049       
050        public NonBlockingStubWrapper(AspectComponent ac, RemoteRef remoteRef) {
051            super(ac,remoteRef);
052        }
053    
054        /**
055        * A more user-friendly constructor.
056        *
057        * @param serverContainer the name of the container where the
058        * server is deployed */
059    
060        public NonBlockingStubWrapper(AspectComponent ac, String serverContainer) {
061            super(ac,serverContainer);
062        }
063    
064    
065        /**
066        * Forward a call to the remote reference.
067        */
068       
069        public Object invoke(Interaction interaction) {
070    
071            if (remoteRef == null) {
072                if (serverContainer == null) {
073                    logger.warn("local call (1) for stub "+interaction.wrappee);
074                    return proceed(interaction);
075                }
076                RemoteContainer rc = Topology.get().getFirstContainer(serverContainer);
077                if (rc == null) {
078                    logger.warn("local call (2) for stub "+interaction.wrappee);
079                    return proceed(interaction);
080                }
081                remoteRef = rc.bindTo(NameRepository.get().getName(interaction.wrappee));
082                if (remoteRef == null) {
083                    logger.warn("local call (3) for stub "+interaction.wrappee+
084                                " ("+rc+","+serverContainer+")");
085                    return proceed(interaction);
086                }
087            }
088    
089            logger.debug(interaction.wrappee + " forwards to the server");
090          
091            /**
092             * These final local variables are required
093             * for the enclosed local class defined below.
094             */
095          
096            final String finalMethodName = interaction.method.getName();
097            final Object[] finalMethodArgs = interaction.args;
098       
099            // I disabled the results...
100            new Thread() {
101                    public void run() {
102                        //results[firstFreeCell] =
103                        remoteRef.invoke( finalMethodName, finalMethodArgs );
104                    }
105                } . start();
106          
107            return null;
108            //new Integer( firstFreeCell );
109        }
110       
111        public void setFirstFreeCell() {
112        }
113    
114        /**
115         * Maximum number of results stored.
116         *
117         * The idea is that if nbMaxOfResults consecutive calls have been made,
118         * the probability that the initial result is to be required is low.
119         */
120        final static protected int nbMaxOfResults = 16;
121    
122        /**
123         * Mailbox for results received from asynchonous calls.
124         * The array is managed as a circular list.
125         */
126        protected Object[] results = new Object[nbMaxOfResults];
127    
128        /** Index of the 1st free cell in results. */
129        protected int firstFreeCell = 0;
130    
131        /**
132         * Return the requested result.
133         *
134         * @param index  the result index
135         * @return       the requested result
136         */
137        public Object getResult( Integer index ) {
138            int ind = index.intValue();
139            Object result = results[ind];
140          
141            // Deference the result in the array.
142            // Once the result have been requested, if we do not set the cell to null,
143            // we may prevent the result object from being garbage collected.
144            results[ind] = null;
145          
146            return result;
147        }
148    
149    }