001    /*
002      Copyright (C) 2001-2002 Renaud Pawlak.
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
015      License along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
017      USA */
018    
019    package org.objectweb.jac.core;
020    
021    import java.util.Vector;
022    import org.aopalliance.intercept.Interceptor;
023    
024    /**
025     * This special aspect component is used by the system to solve
026     * inter-aspect composition issues.
027     *
028     * <p>It is typically used to order the different wrappers at runtime
029     * (see <code>getWeaveTimeRank()</code>) or to check if two aspect
030     * components are incompatible of dependent (see
031     * <code>addIncompatibleACPairs()</code> and
032     * <code>addDependentACPair()</code>).
033     *
034     * @author <a href="mailto:pawlak@cnam.fr">Renaud Pawlak</a>
035     */
036    
037    public class CompositionAspect extends AspectComponent {
038    
039            /** The name of the wrapping order property in the prop file. */
040            //protected static String wrappingOrderProp = "org.objectweb.jac.comp.wrappingOrder";
041            /** The name of the incompatible property in the prop file. */
042            //protected static String incompatibleACsProp = "org.objectweb.jac.comp.imcompatibleACs";
043            /** The name of the dependent property in the prop file. */
044            //protected static String dependentACsProp = "org.objectweb.jac.comp.dependentACs";
045    
046            /** Store the default wrapping order. */
047            protected Vector wrappingOrder = JacPropLoader.wrappingOrder;
048    
049            /** Store the exclusive aspect component pairs. */
050            protected Vector incompatibleACs = JacPropLoader.incompatibleACs;
051    
052            /** Store the dependent aspect component pairs. */
053            protected Vector dependentACs = JacPropLoader.dependentACs;
054    
055            /**
056             * The default contructor (reads the jac.prop file to initialize
057             * the composition aspect). */
058    
059            public CompositionAspect() {
060            }
061    
062            /**
063             * When a wrappee method is beeing wrapped by a wrapper, this
064             * method is upcalled by the system to get the rank of the wrapper
065             * within the wrapping chain (the set of wrappers that allready
066             * wrap the wrappee method).
067             *
068             * @param wrappingChain the set of wrapping methods that allready
069             * wraps the wrappee method
070             * @param wrapper the wrapper that is going be added to the
071             * wrapping chain
072         *
073             * @see Wrapping#wrap(Wrappee,Wrapper,AbstractMethodItem) 
074         */
075            public int getWeaveTimeRank(WrappingChain wrappingChain, Wrapper wrapper) {
076                    int i = 0;
077                    Interceptor[] chain = wrappingChain.chain;
078                    int wrapperRank = wrappingOrder.indexOf(wrapper.getClass().getName());
079                    for (; i < chain.length; i++) {
080                            if (wrapperRank
081                                    <= wrappingOrder.indexOf(chain[i].getClass().getName())) {
082                                    return i;
083                            }
084                    }
085                    /*Log.trace("composition",
086                              "getting weave time rank for "+wrapper+"."+wrappingMethod+ 
087                              "==>" + i + "/" + wrappingChain.size());*/
088                    return i;
089            }
090    
091            /**
092             * Returns true if wrapperType1 has to be run before
093             * wrapperType2. This method is used by
094             * <code>getWeaveTimeRank()</code>.
095             *
096             * @param wrapperType1 the first type to check
097             * @param wrapperType2 the second type to check
098             * @return true if (wrapperType1 < wrapperType2 )
099             * @see #getWeaveTimeRank(WrappingChain,Wrapper)
100             */
101    
102            public final boolean areCorrectlyOrdered(
103                    String wrapperType1,
104                    String wrapperType2) {
105                    /*
106                    Log.trace("composition","areCorrectlyOrdered("+
107                              wrapperType1+"("+i1+"),"+wrapperType2+"("+i1+"))");
108                    */
109                    return (
110                            wrappingOrder.indexOf(wrapperType1)
111                                    <= wrappingOrder.indexOf(wrapperType2));
112                    /*
113                    Log.trace("composition","areCorrectlyOrdered("+
114                              wrapperType1+","+wrapperType2+") -> false");
115                    */
116            }
117    
118            /**
119             * The getter for the wrapping types order.
120             *
121             * @return a vector that contains the ordered wrapper classes */
122    
123            public final Vector getWrappingTypesOrder() {
124                    return wrappingOrder;
125            }
126    
127            /**
128             * Add a new exlusive aspect component pair.
129             * 
130             * <p>If ac1 and ac2 are incompatible, then ac1 cannot be
131             * registered in the Aspect Component Manager if ac2 is already
132             * registered (and reverse).
133             * 
134             * <p>NOTE: this is a reflexive relation.
135             *
136             * @param ac1 the aspect component that is incompatible with ac2
137             * @param ac2 the aspect component that is incompatible with ac1
138             * @see ACManager#register(String,Object) */
139    
140            public final void addIncompatibleACPair(
141                    AspectComponent ac1,
142                    AspectComponent ac2) {
143                    incompatibleACs.add(ac1);
144                    incompatibleACs.add(ac2);
145            }
146    
147            /**
148             * Add a new dependent aspect component pair.
149             * 
150             * <p>If ac1 depends on ac2, then ac1 cannot be registered in the
151             * Aspect Component Manager if ac2 is not already registered.
152             * 
153             * <p>NOTE: this is a transitive relation.
154             *
155             * @param ac1 the aspect component that depends on ac2
156             * @param ac2 the aspect component on which ac1 depends
157             * @see ACManager#register(String,Object) */
158    
159            public final void addDependentACPair(
160                    AspectComponent ac1,
161                    AspectComponent ac2) {
162                    dependentACs.add(ac1);
163                    dependentACs.add(ac2);
164            }
165    
166            /**
167             * Returns true if the aspect components are incompatible.
168             *
169             * <p>NOTE: <code>areIncompatible(ac1,ac2)<code> equals
170             * <code>areIncompatible(ac2,ac1)<code>
171             *
172             * @param ac1 the first aspect component to check
173             * @param ac2 the second aspect component to check
174             * @return true if ac1 is incompatible with ac2
175             * @see #addIncompatibleACPair(AspectComponent,AspectComponent) */
176    
177            public final boolean areIncompatible(
178                    AspectComponent ac1,
179                    AspectComponent ac2) {
180                    for (int i = 0; i < incompatibleACs.size(); i += 2) {
181                            if ((ac1.equals(incompatibleACs.get(i))
182                                    && ac2.equals(incompatibleACs.get(i + 1)))
183                                    || (ac2.equals(incompatibleACs.get(i))
184                                            && ac1.equals(incompatibleACs.get(i + 1)))) {
185                                    return true;
186                            }
187                    }
188                    return false;
189            }
190    
191            /**
192             * Returns true if the aspect components are dependent.
193             *
194             * <p>NOTE: <code>areDependent(ac1,ac2)<code> not equals
195             * <code>areDependent(ac2,ac1)<code>
196             *
197             * @param ac1 the first aspect component to check
198             * @param ac2 the second aspect component to check
199             * @return true if ac1 depends on ac2
200             * @see #addDependentACPair(AspectComponent,AspectComponent) */
201    
202            public final boolean areDependent(
203                    AspectComponent ac1,
204                    AspectComponent ac2) {
205                    for (int i = 0; i < dependentACs.size(); i += 2) {
206                            if ((ac1.equals(dependentACs.get(i))
207                                    && ac2.equals(dependentACs.get(i + 1)))
208                                    || (ac2.equals(dependentACs.get(i))
209                                            && ac1.equals(dependentACs.get(i + 1)))) {
210                                    return true;
211                            }
212                    }
213                    return false;
214            }
215    
216    }