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.naming;
019    
020    import org.aopalliance.intercept.ConstructorInvocation;
021    import org.aopalliance.intercept.MethodInvocation;
022    import org.objectweb.jac.core.*;
023    import org.objectweb.jac.wrappers.ForwardingWrapper;
024    
025    /**
026     * This wrapper class binds an object to the actual named object by
027     * forwarder.
028     *
029     * <p><code>BindingWrapper</code> wraps the JAC object that that has not
030     * been resolved yet by the binding aspect. When a call is performed
031     * on the wrappee, the binder wrapper gets the actual JAC object that
032     * corresponds to the logical name by asking the name repository of
033     * the naming aspect. Then, it creates a forwarding wrapper to this
034     * object and replaces itself with it.
035     * 
036     * <p>The binding aspect uses the naming aspect. Do not try to use it
037     * alone.
038     *
039     * @author <a href="http://cedric.cnam.fr/~pawlak/index-english.html">Renaud Pawlak</a>
040     *
041     * @see ForwardingWrapper */
042    
043    public class BindingWrapper extends Wrapper {
044    
045            /**
046             * Construct a new binding wrapper.
047             *
048             * @param logicalName the name of the wrappee within the naming
049             * aspect */
050    
051            public BindingWrapper(AspectComponent ac, String logicalName) {
052                    super(ac);
053                    this.logicalName = logicalName;
054            }
055    
056            /** The name of the Jac object the binber must bind to. */
057            protected String logicalName;
058    
059            /**
060             * The getter method for the Jac object's name (role method).
061             *
062             * @return the name
063             */
064    
065            public String getLogicalName() {
066                    return logicalName;
067            }
068    
069            /**
070             * This wrapping method binds the wrappee.
071             *
072             * <p>Binds the wrappee to its actual location by creating a new
073             * forwarder wrapper to wrap it. This wrapping method is called
074             * only once since the binder wrapper unwraps itself once the new
075             * wrapper is created.
076             *
077             * @see ForwardingWrapper */
078    
079            public Object bind(Interaction interaction) throws BindingErrorException {
080    
081                    /** Get the name repository */
082                    NameRepository repository = (NameRepository) NameRepository.get();
083    
084                    if (repository == null) {
085                            throw new BindingErrorException("Binding aspect cannot work without the naming aspect.");
086                    }
087    
088                    /** Get the actual reference of the object by invoking the
089                        repository. */
090    
091                    Object object = repository.getObject(logicalName);
092    
093                    //if (true) return null;
094    
095                    if (object == null) {
096                            throw new BindingErrorException(
097                                    "Object '" + logicalName + "' not found in the repository.");
098                    }
099    
100                    //      RemoteRef rr = null;
101                    Object to_forward = null;
102    
103                    /** If their is several objects for the name, then it is a
104                        replicated object. We try to bind to the local one if
105                        exist. It not, we will bind to the first one. This is the
106                        only interaction with the distribution aspect. */
107    
108                    //        if (objects.length > 1) {
109                    //            for (int i = 0; i < objects.length; i++) {
110                    //               if ( ! ((Wrappee)objects[i]).isWrappedByClass ( StubWrapper.class ) ) {
111                    //                  to_forward = objects[i];
112                    //               } else {
113                    //                  if ( ((RemoteRef) ((Wrappee)objects[i]).invokeRoleMethod ( 
114                    //                     "org.objectweb.jac.dist.StubWrapper", "getRemoteRef", new Class[] {}, new Object[] {} ))
115                    //                       . getRemCont().isLocal () ) {
116                    //                     to_forward = objects[i];
117                    //                  }
118                    //               }
119                    //            }
120                    //         }
121    
122                    //         if ( to_forward == null ) {
123                    //            to_forward = objects[0];
124                    //        }
125    
126                    /** We replace the binder with a forwarder. */
127    
128                    ForwardingWrapper forwarder =
129                            new ForwardingWrapper(getAspectComponent(), object);
130                    Wrapping.unwrapAll(interaction.wrappee, null, this);
131                    Wrapping.wrapAll(interaction.wrappee, null, forwarder);
132    
133                    /** We redo the call (that will be forwarded this time */
134                    Object ret =
135                            interaction.method.invoke(interaction.wrappee, interaction.args);
136                    return ret;
137    
138            }
139    
140            public Object invoke(MethodInvocation invocation) throws Throwable {
141                    return bind((Interaction) invocation);
142            }
143    
144            public Object construct(ConstructorInvocation invocation)
145                    throws Throwable {
146                    throw new Exception("Wrapper "+this+" does not support construction interception.");
147            }
148    
149    }